ntohs, ntohl, htons,htonl的比較和詳解
在C/C++寫網絡程序的時候,往往會遇到字節的網絡順序和主機順序的問題。
這時就可能用到htons(), ntohl(), ntohs(),htons()這4個網絡字節順序與本地字節順序之間的轉換函數:之所以需要這些函數是因為計算機數據表示存在兩種字節順序:NBO與HBO。
網絡字節順序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。
由于這個原因不同體系結構的機器之間無法通信,所以要轉換成一種約定的數序,也就是網絡字節順序,其實就是如同power pc那樣的順序 。在PC開發中有ntohl和htonl函數可以用來進行網絡字節和主機字節的轉換。
在Linux系統下:htonl(),htons(), ntohl(), ntohs()的頭文件及函數定義:
#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); 在windows系統下:htonl(),htons(), ntohl(), ntohs(), inet_addr()使用說明
ntohs()
簡述:
將一個無符號短整形數從網絡字節順序轉換為主機字節順序。
#include <winsock.h>
u_short PASCAL FAR ntohs( u_short netshort);
netshort:一個以網絡字節順序表達的16位數。
注釋:
本函數將一個16位數由網絡字節順序轉換為主機字節順序。
返回值:ntohs()返回一個以主機字節順序表達的數。
ntohl()
簡述:
將一個無符號長整形數從網絡字節順序轉換為主機字節順序。
#include <winsock.h>
u_long PASCAL FAR ntohl( u_long netlong);
netlong:一個以網絡字節順序表達的32位數。
注釋:
本函數將一個32位數由網絡字節順序轉換為主機字節順序。
返回值:
ntohl()返回一個以主機字節順序表達的數。
htons()
簡述:
將主機的無符號短整形數轉換成網絡字節順序。//將無符號短整型主機字節序轉換為網絡字節序
#include <winsock.h>
u_short PASCAL FAR htons( u_short hostshort);
hostshort:主機字節順序表達的16位數。
注釋:
本函數將一個16位數從主機字節順序轉換成網絡字節順序。
返回值:
htons()返回一個網絡字節順序的值。
簡單地說,htons()就是將一個數的高低位互換
(如:12 34 --> 34 12)
VB表示:
MsgBox Hex(htons(&H1234))
顯示值為 3412
htonl()
簡述:
將主機的無符號長整形數轉換成網絡字節順序。//將無符號長整型網絡字節序轉換為主機字節序
#include <winsock.h>
u_long PASCAL FAR htonl( u_long hostlong);
hostlong:主機字節順序表達的32位數。
注釋:
本函數將一個32位數從主機字節順序轉換成網絡字節順序。
返回值:
htonl()返回一個網絡字節順序的值。
簡述:
將一個點間隔地址轉換成一個in_addr。
#include <winsock.h>
unsigned long PASCAL FAR inet_addr( const struct FAR* cp);
cp:一個以Internet標準“.”間隔的字符串。例如202.38.214.xx
當IP地址為255.255.255.255是被認為無效IP地址。
本函數解釋cp參數中的字符串,這個字符串用Internet的“.”間隔格式表示一個數字的Internet地址。
返回值:
一個無符號長整形數,可用作Internet地址。所有Internet地址以網絡字節順序返回(字節從左到右排列)。
inet_ntoa()
簡述:
將網絡地址轉換成“.”點隔的字符串格式。
#include <winsock.h>
char FAR* PASCAL FAR inet_ntoa( struct in_addr in);
in:一個表示Internet主機地址的結構。
注釋:
本函數將一個用in參數所表示的Internet地址結構轉換成以“.” 間隔的諸如“a.b.c.d”的字符串形式。請注意inet_ntoa()返回的字符串存放在WINDOWS套接口實現所分配的內存中。應用程序不應假設該內存是如何分配的。在同一個線程的下一個WINDOWS套接口調用前,數據將保證是有效。
當IP地址為255.255.255.255是認為有效IP地址。這是與inet_addr()的區別
返回值:
若無錯誤發生,inet_ntoa()返回一個字符指針。否則的話,返回NULL。其中的數據應在下一個WINDOWS套接口調用前復制出來。
inet_aton()
與inet_ntoa()作用相反。
inet_pton()
簡述:
本函數將點分十進制轉換為整數
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int inet_pton(int af, const char *src, void *dst);
這個函數轉換字符串到網絡地址,第一個參數af是地址族,轉換后存在dst中
inet_pton 是inet_addr的擴展,支持的多地址族有下列:
af = AF_INET
src為指向字符型的地址,即ASCII的地址的首地址(ddd.ddd.ddd.ddd格式的),函數將該地址
轉換為in_addr的結構體,并復制在*dst中
af =AF_INET6
src為指向IPV6的地址,,函數將該地址轉換為in6_addr的結構體,并復制在*dst中
如果函數出錯將返回一個負值,并將errno設置為EAFNOSUPPORT,如果參數af指定的地址族和src格式不對,函數將返回0。
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
這個函數轉換網絡二進制結構到ASCII類型的地址,參數的作用和上面相同,只是多了一個參數socklen_t cnt,他是所
指向緩存區dst的大小,避免溢出,如果緩存區太小無法存儲地址的值,則返回一個空指針,并將errno置為ENOSPC
atoi()
array to integer將字符串轉換為整形數
首先,假設你已經有了一個sockaddr_in結構體ina,你有一個IP地址"132.241.5.10" 要儲存在其中,你就要用到函數inet_addr(),將IP地址從 點數格式轉換成無符號長整型。
使用方法如下:
ina.sin_addr.s_addr = inet_addr("132.241.5.10");
注意,inet_addr()返回的地址已經是網絡字節格式,所以你無需再調用 函數htonl()。
我們現在發現上面的代碼片斷不是十分完整的,因為它沒有錯誤檢查。 顯而易見,當inet_addr()發生錯誤時返回-1。記住這些二進制數字?(無符 號數)-1僅僅和IP地址255.255.255.255相符合!這可是廣播地址!大錯特 錯!記住要先進行錯誤檢查。
好了,現在你可以將IP地址轉換成長整型了。有沒有其相反的方法呢? 它可以將一個in_addr結構體輸出成點數格式?這樣的話,你就要用到函數 inet_ntoa()("ntoa"的含義是"network to ascii"),就像這樣:
printf("%s",inet_ntoa(ina.sin_addr));
它將輸出IP地址。需要注意的是inet_ntoa()將結構體in-addr作為一 個參數,不是長整形。同樣需要注意的是它返回的是一個指向一個字符的 指針。它是一個由inet_ntoa()控制的靜態的固定的指針,所以每次調用 inet_ntoa(),它就將覆蓋上次調用時所得的IP地址。例如:
char *a1, *a2;
a1 = inet_ntoa(ina1.sin_addr); /* 這是198.92.129.1 */
a2 = inet_ntoa(ina2.sin_addr); /* 這是132.241.5.10 */
printf("address 1: %s ",a1);
printf("address 2: %s ",a2);
輸出如下:
address 1: 132.241.5.10
address 2: 132.241.5.10
假如你需要保存這個IP地址,使用strcopy()函數來指向你自己的字符指針。
***********************************************************************************************************************************
測試代碼如下#include
#include
#include
#include
#include
int main(int argc, char* argv[])
{
struct in_addr addr1,addr2;
ulong l1,l2;
l1= inet_addr("192.168.0.74");
l2 = inet_addr("211.100.21.179");
memcpy(&addr1, &l1, 4);
memcpy(&addr2, &l2, 4);
printf("%s : %s ", inet_ntoa(addr1), inet_ntoa(addr2)); //注意這一句的運行結果
printf("%s ", inet_ntoa(addr1));
printf("%s ", inet_ntoa(addr2));
return 0;
}
實際運行結果如下:
192.168.0.74 : 192.168.0.74 //從這里可以看出,printf里的inet_ntoa只運行了一次。
192.168.0.74
211.100.21.179
inet_ntoa返回一個char *,而這個char *的空間是在inet_ntoa里面靜態分配的,所以inet_ntoa后面的調用會覆蓋上一次的調用。第一句printf的結果只能說明在printf里面的可變參數的求值是從右到左的,僅此而已。
RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成