小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

ntohs, ntohl, htons,htonl的比較和詳解

 LibraryOfKevin 2012-02-22
在C/C++寫(xiě)網(wǎng)絡(luò)程序的時(shí)候,往往會(huì)遇到字節(jié)的網(wǎng)絡(luò)順序和主機(jī)順序的問(wèn)題。
這時(shí)就可能用到htons(), ntohl(), ntohs(),htons()這4個(gè)網(wǎng)絡(luò)字節(jié)順序與本地字節(jié)順序之間的轉(zhuǎn)換函數(shù):
      htonl()--"Host to Network Long int"     32Bytes
      ntohl()--"Network to Host Long int"     32Bytes
      htons()--"Host to Network Short int"   16Bytes
      ntohs()--"Network to Host Short int"   16Bytes

之所以需要這些函數(shù)是因?yàn)橛?jì)算機(jī)數(shù)據(jù)表示存在兩種字節(jié)順序:NBO與HBO。

網(wǎng)絡(luò)字節(jié)順序NBO(Network Byte Order):
      按從高到低的順序存儲(chǔ),在網(wǎng)絡(luò)上使用統(tǒng)一的網(wǎng)絡(luò)字節(jié)順序,可以避免兼容性問(wèn)題。

主機(jī)字節(jié)順序(HBO,Host Byte Order):
      不同的機(jī)器HBO不相同,與CPU設(shè)計(jì)有關(guān),數(shù)據(jù)的順序是由cpu決定的,而與操作系統(tǒng)無(wú)關(guān)。 
      如 Intel   x86結(jié)構(gòu)下,short型數(shù)0x1234表示為34 12, int型數(shù)0x12345678表示為78 56 34 12 。
      如IBM   power PC結(jié)構(gòu)下,short型數(shù)0x1234表示為12   34, int型數(shù)0x12345678表示為12 34 56 78。   

 由于這個(gè)原因不同體系結(jié)構(gòu)的機(jī)器之間無(wú)法通信,所以要轉(zhuǎn)換成一種約定的數(shù)序,也就是網(wǎng)絡(luò)字節(jié)順序,其實(shí)就是如同power   pc那樣的順序 。在PC開(kāi)發(fā)中有ntohl和htonl函數(shù)可以用來(lái)進(jìn)行網(wǎng)絡(luò)字節(jié)和主機(jī)字節(jié)的轉(zhuǎn)換。


在Linux系統(tǒng)下:htonl(),htons(), ntohl(), ntohs()的頭文件及函數(shù)定義:
  #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系統(tǒng)下htonl(),htons(), ntohl(), ntohs(), inet_addr()使用說(shuō)明

ntohs()  

  簡(jiǎn)述:
  將一個(gè)無(wú)符號(hào)短整形數(shù)從網(wǎng)絡(luò)字節(jié)順序轉(zhuǎn)換為主機(jī)字節(jié)順序。
  #include <winsock.h>
  u_short PASCAL FAR ntohs( u_short netshort);
  netshort:一個(gè)以網(wǎng)絡(luò)字節(jié)順序表達(dá)的16位數(shù)。
  注釋:
  本函數(shù)將一個(gè)16位數(shù)由網(wǎng)絡(luò)字節(jié)順序轉(zhuǎn)換為主機(jī)字節(jié)順序。
  返回值:ntohs()返回一個(gè)以主機(jī)字節(jié)順序表達(dá)的數(shù)。

ntohl() 

       簡(jiǎn)述:
  將一個(gè)無(wú)符號(hào)長(zhǎng)整形數(shù)從網(wǎng)絡(luò)字節(jié)順序轉(zhuǎn)換為主機(jī)字節(jié)順序。
 ?。nclude <winsock.h>
  u_long PASCAL FAR ntohl( u_long netlong);
  netlong:一個(gè)以網(wǎng)絡(luò)字節(jié)順序表達(dá)的32位數(shù)。
  注釋:
  本函數(shù)將一個(gè)32位數(shù)由網(wǎng)絡(luò)字節(jié)順序轉(zhuǎn)換為主機(jī)字節(jié)順序。
  返回值:
  ntohl()返回一個(gè)以主機(jī)字節(jié)順序表達(dá)的數(shù)。

htons()
       簡(jiǎn)述:
  將主機(jī)的無(wú)符號(hào)短整形數(shù)轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序。//將無(wú)符號(hào)短整型主機(jī)字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序
  #include <winsock.h>
  u_short PASCAL FAR htons( u_short hostshort);
  hostshort:主機(jī)字節(jié)順序表達(dá)的16位數(shù)。
  注釋:
  本函數(shù)將一個(gè)16位數(shù)從主機(jī)字節(jié)順序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序。
  返回值:
  htons()返回一個(gè)網(wǎng)絡(luò)字節(jié)順序的值。
  簡(jiǎn)單地說(shuō),htons()就是將一個(gè)數(shù)的高低位互換
  (如:12 34 --> 34 12)
  VB表示:
  MsgBox Hex(htons(&H1234))
  顯示值為 3412

htonl()
      簡(jiǎn)述:
  將主機(jī)的無(wú)符號(hào)長(zhǎng)整形數(shù)轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序。//將無(wú)符號(hào)長(zhǎng)整型網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換為主機(jī)字節(jié)序
  #include <winsock.h>
  u_long PASCAL FAR htonl( u_long hostlong);
  hostlong:主機(jī)字節(jié)順序表達(dá)的32位數(shù)。
  注釋:
  本函數(shù)將一個(gè)32位數(shù)從主機(jī)字節(jié)順序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序。
  返回值:
  htonl()返回一個(gè)網(wǎng)絡(luò)字節(jié)順序的值。

inet_addr()

       簡(jiǎn)述:
       將一個(gè)點(diǎn)間隔地址轉(zhuǎn)換成一個(gè)in_addr。
  #include <winsock.h>
  unsigned long PASCAL FAR inet_addr( const struct FAR* cp);
  cp:一個(gè)以Internet標(biāo)準(zhǔn)“.”間隔的字符串。例如202.38.214.xx
       當(dāng)IP地址為255.255.255.255是被認(rèn)為無(wú)效IP地址。
       本函數(shù)解釋cp參數(shù)中的字符串,這個(gè)字符串用Internet的“.”間隔格式表示一個(gè)數(shù)字的Internet地址。
    返回值:
    一個(gè)無(wú)符號(hào)長(zhǎng)整形數(shù),可用作Internet地址。所有Internet地址以網(wǎng)絡(luò)字節(jié)順序返回(字節(jié)從左到右排列)。

inet_ntoa()
    簡(jiǎn)述:
  將網(wǎng)絡(luò)地址轉(zhuǎn)換成“.”點(diǎn)隔的字符串格式。
  #include <winsock.h>
  char FAR* PASCAL FAR inet_ntoa( struct in_addr in);
  in:一個(gè)表示Internet主機(jī)地址的結(jié)構(gòu)。
  注釋:
本函數(shù)將一個(gè)用in參數(shù)所表示的Internet地址結(jié)構(gòu)轉(zhuǎn)換成以“.” 間隔的諸如“a.b.c.d”的字符串形式。請(qǐng)注意
inet_ntoa()返回的字符串存放在WINDOWS套接口實(shí)現(xiàn)所分配的內(nèi)存中。應(yīng)用程序不應(yīng)假設(shè)該內(nèi)存是如何分配的。在同一個(gè)線程的下一個(gè)WINDOWS套接口調(diào)用前,數(shù)據(jù)將保證是有效。
當(dāng)IP地址為255.255.255.255是認(rèn)為有效IP地址。這是與inet_addr()的區(qū)別
  返回值:
  若無(wú)錯(cuò)誤發(fā)生,inet_ntoa()返回一個(gè)字符指針。否則的話,返回NULL。其中的數(shù)據(jù)應(yīng)在下一個(gè)WINDOWS套接口調(diào)用前
復(fù)制出來(lái)。

inet_aton()
    與inet_ntoa()作用相反。

inet_pton()
    簡(jiǎn)述:
    本函數(shù)將點(diǎn)分十進(jìn)制轉(zhuǎn)換為整數(shù)
      #include <sys/types.h>
  #include <sys/socket.h>
  #include <arpa/inet.h>
  int inet_pton(int af, const char *src, void *dst);
  這個(gè)函數(shù)轉(zhuǎn)換字符串到網(wǎng)絡(luò)地址,第一個(gè)參數(shù)af是地址族,轉(zhuǎn)換后存在dst中
    inet_pton 是inet_addr的擴(kuò)展,支持的多地址族有下列:
  af = AF_INET
  src為指向字符型的地址,即ASCII的地址的首地址(ddd.ddd.ddd.ddd格式的),函數(shù)將該地址
  轉(zhuǎn)換為in_addr的結(jié)構(gòu)體,并復(fù)制在*dst中
  af =AF_INET6
  src為指向IPV6的地址,,函數(shù)將該地址轉(zhuǎn)換為in6_addr的結(jié)構(gòu)體,并復(fù)制在*dst中
  如果函數(shù)出錯(cuò)將返回一個(gè)負(fù)值,并將errno設(shè)置為EAFNOSUPPORT,如果參數(shù)af指定的地址族和src格式不對(duì),函數(shù)將返
回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);
  這個(gè)函數(shù)轉(zhuǎn)換網(wǎng)絡(luò)二進(jìn)制結(jié)構(gòu)到ASCII類型的地址,參數(shù)的作用和上面相同,只是多了一個(gè)參數(shù)socklen_t cnt,他是所

    指向緩存區(qū)dst的大小,避免溢出,如果緩存區(qū)太小無(wú)法存儲(chǔ)地址的值,則返回一個(gè)空指針,并將errno置為ENOSPC

atoi()

array to integer將字符串轉(zhuǎn)換為整形數(shù)



首先,假設(shè)你已經(jīng)有了一個(gè)sockaddr_in結(jié)構(gòu)體ina,你有一個(gè)IP地址"132.241.5.10" 要儲(chǔ)存在其中,你就要用到函數(shù)inet_addr(),將IP地址從 點(diǎn)數(shù)格式轉(zhuǎn)換成無(wú)符號(hào)長(zhǎng)整型。
使用方法如下:
ina.sin_addr.s_addr = inet_addr("132.241.5.10");
注意,inet_addr()返回的地址已經(jīng)是網(wǎng)絡(luò)字節(jié)格式,所以你無(wú)需再調(diào)用 函數(shù)htonl()。
我們現(xiàn)在發(fā)現(xiàn)上面的代碼片斷不是十分完整的,因?yàn)樗鼪](méi)有錯(cuò)誤檢查。 顯而易見(jiàn),當(dāng)inet_addr()發(fā)生錯(cuò)誤時(shí)返回-1。記住這些二進(jìn)制數(shù)字?(無(wú)符 號(hào)數(shù))-1僅僅和IP地址255.255.255.255相符合!這可是廣播地址!大錯(cuò)特 錯(cuò)!記住要先進(jìn)行錯(cuò)誤檢查。
好了,現(xiàn)在你可以將IP地址轉(zhuǎn)換成長(zhǎng)整型了。有沒(méi)有其相反的方法呢? 它可以將一個(gè)in_addr結(jié)構(gòu)體輸出成點(diǎn)數(shù)格式?這樣的話,你就要用到函數(shù) inet_ntoa()("ntoa"的含義是"network to ascii"),就像這樣: 
printf("%s",inet_ntoa(ina.sin_addr));
它將輸出IP地址。需要注意的是inet_ntoa()將結(jié)構(gòu)體in-addr作為一 個(gè)參數(shù),不是長(zhǎng)整形。同樣需要注意的是它返回的是一個(gè)指向一個(gè)字符的 指針。它是一個(gè)由inet_ntoa()控制的靜態(tài)的固定的指針,所以每次調(diào)用 inet_ntoa(),它就將覆蓋上次調(diào)用時(shí)所得的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
假如你需要保存這個(gè)IP地址,使用strcopy()函數(shù)來(lái)指向你自己的字符指針。

***********************************************************************************************************************************

測(cè)試代碼如下

#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));    //注意這一句的運(yùn)行結(jié)果

         printf("%s ", inet_ntoa(addr1));
         printf("%s ", inet_ntoa(addr2));
         return 0;
}
實(shí)際運(yùn)行結(jié)果如下:
192.168.0.74 : 192.168.0.74       //從這里可以看出,printf里的inet_ntoa只運(yùn)行了一次。
192.168.0.74
211.100.21.179

inet_ntoa返回一個(gè)char *,而這個(gè)char *的空間是在inet_ntoa里面靜態(tài)分配的,所以inet_ntoa后面的調(diào)用會(huì)覆蓋上一次的調(diào)用。第一句printf的結(jié)果只能說(shuō)明在printf里面的可變參數(shù)的求值是從右到左的,僅此而已。


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多