01大小端、網絡字節序、地址轉換函數的使用

#include <stdio.h>
#include <string.h>

#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <errno.h>

/*
    man 7 ip
    ipv4套接字地址結構

struct sockaddr_in {
    sa_family_t    sin_family; //address family: AF_INET 
    in_port_t      sin_port;   //port in network byte order
    struct in_addr sin_addr;   //internet address 
    };

 //Internet address
 struct in_addr {
     uint32_t       s_addr;     // address in network byte order 
 };

typedef uint32_t in_addr_t;

struct in_addr {
   in_addr_t s_addr;
};



man htonl
//字節排序函數
#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);      //返回網絡字節序

uint16_t htons(uint16_t hostshort);     //返回網絡字節序

uint32_t ntohl(uint32_t netlong);   //返回主機字節序

uint16_t ntohs(uint16_t netshort);  //返回主機字節序

h代表host;n代表network s代表short;l代表long


*/

//測試大小端
#if 0
void test()
{
    unsigned int data=0x12345678;
    char * p =NULL;
    p= (char *)&data;

    printf("%x, %x, %x, %x \n", p[0], p[1], p[2], p[3]);
    if(p[0] == 0x78)
    {
        printf("當前系統是小端模式\n");  
    }
    else
    {
        printf("當前系統是大端模式\n");  
    }

    printf("把本地字節轉換成網絡字節\n");

    uint32_t mynetdata = htonl(data);
    p = (char *)&mynetdata;

    if(p[0] == 0x78)
    {
        printf("網絡字節序是是小端模式\n");
    }
    else
    {
        printf("網絡字節序是是大端模式\n");
    }

}

#endif
/*
    信號處理函數遇上可重入和不可重入函數
    可重入函數概念
    1、爲了增強程序的穩定性,在信號處理函數中應使用可重入函數。 
    2、所謂可重入函數是指一個可以被多個任務調用的過程,任務在調用時
      不必擔心數據是否會出錯。因爲進程在收到信號後,就將跳轉到信號處理
      函數去接着執行。如果信號處理函數中使用了不可重入函數,那麼信號
      處理函數可能會修改原來進程中不應該被修改的數據,這樣進程從信號
      處理函數中返回接着執行時,可能會出現不可預料的後果。不可再入函數
      在信號處理函數中被視爲不安全函數。
  3、滿足下列條件的函數多數是不可重入的:
  (1)使用靜態的數據結構,如getlogin(),gmtime(),getgrgid(),getgrnam(),
            getpwuid()以及getpwnam()等等;
  (2)函數實現時,調用了malloc()或者free()函數;
  (3)實現時使用了標準I/O函數的
*/

/*
點分十進制字符串與32位的網絡字節序二進制值轉換IPV4地址

#include <arpa/inet.h>

            //點分十進制的字符串轉化爲32位網絡字節序
       int inet_aton(const char *cp, struct in_addr *inp);//1

            //點分十進制的字符串轉化爲32位網絡字節序
       in_addr_t inet_addr(const char *cp);//2 已經被廢棄,應使用4 最好使用5

            //32位網絡字節序轉化爲點分十進制的字符串
       char *inet_ntoa(struct in_addr in);//4


       in_addr_t inet_network(const char *cp);
       struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host);
       in_addr_t inet_lnaof(struct in_addr in);
       in_addr_t inet_netof(struct in_addr in);



       注意:
       char *inet_ntoa(struct in_addr in);//4

       1)函數返回值指向的字符串駐留在靜態內存中,是不可重入的,
       2)函數的參數是一個結構體,而不是指針.
       答案:正常使用應該是傳入一個指針,主調函數分配內存,使用完再釋放!
       linux內核不這麼做,你就分配個內存給到我,我給你轉一把,然後把
       內存地址給到你,其實還是你分配的那個內存。
       借用了你分配的內存了。       
*/
//地址轉換函數
#if 0
void test()
{                                                                           
        const char *cp = "192.168.66.128";
        struct in_addr inp;
        int ret;
    ret = inet_aton(cp, &inp);//1
        if(ret == 0)
        {
            printf("%s is invalid\n", cp);
        }

        //請你深刻的理解爲什麼這個地方 要求傳入的是元素
        /*
           //Internet address. 
       struct in_addr {
           u_int32_t      s_addr;     // address in network byte order 
       };
       */
     printf("ip is %s\n", inet_ntoa(inp)); 
}

#endif
/*
p代表表達(presentation)  n代表數值(numeric) 
 af  argument  must  be either AF_INET or AF_INET6.
//點分十進制-》32位二進制IPV4或者   
int inet_pton(int af, const char *src, void *dst);

const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);


*/
//地址轉換函數

#if 1
void test()
{
    char ip[16] = {0};
    char addptr[16] = {0};
    const char *cp = "192.168.66.128";
    int ret;
    socklen_t size = sizeof(ip);
    char *p = NULL;

    //AF_INET or AF_INET6.
    ret = inet_pton(AF_INET, cp, (void *)addptr);
    if (ret == 0)
    {
        printf("%s is invalid\n", cp);
        return;
    }
    else if (ret == -1)
    {
        if (errno == EAFNOSUPPORT)
            perror("不支持的協議族");
        if (errno == ENOSPC)
            perror("分配的內存不夠");
        return;
    }

    if (ip != NULL)
    {
        p = (char *)inet_ntop(AF_INET, addptr, ip, size);
    }
    if (errno == ENOSPC)
    {
        perror("分配的內存size不夠");
        return;
    }
    if (p != ip)
    {
        perror("inet_ntop");
        return;
    }
    printf("ip is %s\n", ip);
}

#endif

int main()
{
    test();
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章