htonl() htons() ntohl() ntohs()及inet_ntoa() inet_addr()的用法
一、網絡字節序和主機字節序
注:其中的h表示“host”,n表示“net”,l表示“long”,s表示“short”,a表示“ascii”,addr表示“in_addr結構體”
這些函數都與網絡字節序和主機字節序列的轉換,首先介紹一下網絡字節序和主機字節序列及兩者之間的轉換關系。
網絡字節順序NBO(Network Byte Order):
按從高到低的順序存儲,在網絡上使用統一的網絡字節順序,可以避免兼容性問題。
主機字節順序(HBO,Host Byte Order):
不同的機器HBO不相同,與CPU設計有關,數據的順序是由cpu決定的,而與操作系統無關。
如 Intel x86結構下,short型數0x1234表示為34 12, int型數0x12345678表示為78 56 34 12 。
如IBM power PC結構下,short型數0x1234表示為12 34, int型數0x12345678表示為12 34 56 78
以IP地址127.0.0.1為例,看看兩者之間是如何轉換的:
1 第一步 127 . 0 . 0 . 1 把IP地址每一部分轉換為8位的二進制數。
2 第二步 01111111.00000000.00000000.00000001 = 2130706433 (主機字節序)
3 然后把上面的四部分二進制數從右往左按部分重新排列,那就變為:
4 第三步 00000001.00000000.00000000.01111111 = 16777343 (網絡字節序)
【示例】
1 SOCKADDR_IN addrSrv; 2 addrSrv.sin_addr.S_un.S_addr=htonl(2130706433); 3 addrSrv.sin_family=AF_INET; 4 addrSrv.sin_port=htons(6000);
先是定義了一個IP地址結構體addrSrv,然后初始化它的IP時addrSrv.sin_addr.S_un.S_addr必須是賦值IP地址的網絡字節序,htonl函數的作用是把一個主機字節序轉換為網絡字節序,也就是上面轉換過程中第二步轉換為第三步的作用,127.0.0.1的主機字節序是2130706433,把主機字節序2130706433轉換為網絡字節序就是htonl(2130706433)=16777343,所以如果你知道網絡字節序是16777343的話,addrSrv.sin_addr.S_un.S_addr=htonl(2130706433);與addrSrv.sin_addr.S_un.S_addr=16777343;是完全一樣的。
1 addrSrv.sin_addr.S_un.S_addr=htonl(2130706433);//這句還可以寫為下面的樣子 2 addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); 3 //結果是完全一樣的。 4 //可見inet_addr函數的轉換作用就是上面的第一步到第三步的轉換。
下面再看端口的主機字節序與網絡字節序的轉換。以6000端口為例。
1 第一步 00010111 01110000 = 6000 (主機字節序) 2 //端口號其實就已經是主機字節序了,首先要把端口號寫為16位的二進制數,分前8位和后8位。 3 第二步 01110000 00010111 = 28695 (網絡字節序) 4 //然后把主機字節序的前八位與后八位調換位置組成新的16位二進制數,這新的16位二進制數就是網絡字節序的二進制表示了。
因此,如果你知道6000端口的網絡字節序是28695的話。 addrSrv.sin_port=htons(6000);可以直接寫為 addrSrv.sin_port=28695;結果是一樣的,htons的作用就是把端口號主機字節序轉換為網絡字節序。
二、htonl() htons() ntohl() ntohs()及inet_ntoa() inet_addr()的用法
htonl()函數:將主機字節序轉換為網絡字節序
函數原型:
1 u_long PASCAL FAR htonl (u_long hostlong);
htons()函數:將主機字節序轉換為網絡字節序
函數原型:
1 u_short PASCAL FAR htons (u_short hostshort);
ntohl()函數:網絡順序轉換成主機順序
函數原型:
1 u_long PASCAL FAR ntohl (u_long netlong);
ntohs()函數:網絡順序轉換成主機順序
函數原型:
1 u_short PASCAL FAR ntohs (u_short netshort);
inet_ntoa()函數:接受一個in_addr結構體類型的參數並返回一個以點分十進制格式表示的IP地址字符串。
函數原型:
1 char FAR * PASCAL FAR inet_ntoa (struct in_addr in);
inet_addr()函數:需要一個字符串作為其參數,該字符串指定了以點分十進制格式表示的IP地址(例如:192.168.0.16)。
而且inet_addr函數會返回一個適合分配給S_addr的u_long類型的數值。
函數原型:
1 unsigned long PASCAL FAR inet_addr (const char FAR * cp);
