小尾端和大尾端及htons函式解釋

2021-08-17 13:52:32 字數 4009 閱讀 9949

big endian:大尾端,也稱大端(高位)優先儲存。

little endian:小尾端,也稱小端(低位)優先儲存。

是按照高位位元組和地位位元組儲存的,不是位。

如下00000000 00000000 00000000 00000001的儲存

大尾端: 00000000 00000000 00000000 00000001

addr+0   addr+1    addr+2  addr+3    //先存高有效位(在低位址) 

小尾端: 00000001 00000000 00000000 00000000

addr+0   addr+1    addr+2  addr+3    //先存低有效位(在低位址)

計算機資料儲存有兩種位元組優先順序:高位位元組優先和低位位元組優先。internet上資料以高位位元組優先順序在網路上傳輸,所以對於在內部是以低位位元組優先方式儲存資料的機器,在internet上傳輸資料時就需要進行轉換,否則就會出現資料不一致。

下面是幾個位元組順序轉換函式:

·htonl():把32位值從主機位元組序轉換成網路位元組序

·htons():把16位值從主機位元組序轉換成網路位元組序

·ntohl():把32位值從網路位元組序轉換成主機位元組序

·ntohs():把16位值從網路位元組序轉換成主機位元組序

在intel機器下,執行以下程式

main(

)得到的結果是4096,初一看感覺很怪。

解釋如下,數字16的16進製表示為0x0010,數字4096的16進製表示為0x1000。 由於intel機器是小尾端,儲存數字16時實際順序為1000,儲存4096時實際順序為0010。因此在傳送網路包時為了報文中資料為0010,需要經過htons進行位元組轉換。如果用ibm等大尾端機器,則沒有這種位元組順序轉換,但為了程式的可移植性,也最好用這個函式。

1、htonl ()和ntohl( )

u_long pascal far ntohl (u_long netlong);

u_short pascal far ntohs (u_short netshort);

ntohl( )-----網路順序轉換成主機順序

u_long pascal far htonl (u_long hostlong);

u_short pascal far htons (u_short hostshort);

htonl ()-----主機順序轉換成網路順序

2、inet_addr( )和inet_ntoa ( )

unsigned long pascal far inet_addr (const char far * cp);

char far * pascal far inet_ntoa (struct in_addr in);

inet_addr函式需要乙個字串作為其引數,該字串指定了以點分十進位制格式表示的ip位址(例如:192.168.0.16)。而且inet_addr函式會返回乙個適合分配給s_addr的u_long型別的數值。

inet_ntoa函式會完成相反的轉換,它接受乙個in_addr結構體型別的引數並返回乙個以點分十進位制格式表示的ip位址字串。

sockaddr_in , sockaddr , in_addr區別

struct   sockaddr   ;  

上面是通用的socket位址,具體到internet   socket,用下面的結構,二者可以進行型別轉換  

struct   sockaddr_in   ;  

struct   in_addr就是32位ip位址。  

struct   in_addr   s_un_b;

struct s_un_w;

u_long s_addr; 

} s_un;

#define s_addr  s_un.s_addr

};  

inet_addr()是將乙個點分制的ip位址(如192.168.0.1)轉換為上述結構中需要的32位ip位址(0xc0a80001)。

填值的時候使用sockaddr_in結構,而作為函式(如socket, listen, bind等)的引數傳入的時候轉換成sockaddr結構就行了,畢竟都是16個字元長。

通常的用法是:  

int   sockfd;  

struct   sockaddr_in   my_addr;  

sockfd   =   socket(af_inet,   sock_stream,   0);     

my_addr.sin_family   =   af_inet;     

my_addr.sin_port   =   htons(myport);     

my_addr.sin_addr.s_addr   =   inet_addr("192.168.0.1");  

bzero(&(my_addr.sin_zero),   8);     

bind(sockfd,   (struct   sockaddr   *)&my_addr,   sizeof(struct   sockaddr));

可以用c++做個不太準確的假設。  

sockaddr是base   class    

sockaddr_in   等是derived   class  

如此一來,bind,   connect   ,   sendto   ,   recvfrom等函式就可以使用base class  

來處理多種不同的derived   class了。  

但是實際上,這是沒有繼承關係資料結構(c嘛),所以需要強制造型來轉換資料型別。正因為如此,在sendto的時候需要給出len長度,因為不同的sockaddr_xx實現長度並不相同。

名詞解析:

主機位元組序:

不同的cpu有不同的位元組序型別,這些位元組序是指整數在記憶體中儲存的順序,這個叫做主機序。最常見的有兩種 1.little endian:高位元組存高位址,低位元組存低位址 2.big endian:高位元組存低位址,低位元組存高位址

網路位元組序:

網路位元組順序是tcp/ip中規定好的一種資料表示格式,它與具體的cpu型別、作業系統等無關,從而可以保證資料在不同主機之間傳輸時能夠被正確解釋。網路位元組順序採用big endian排序方式。

為了進行轉換bsd socket提供了轉換的函式,有下面四個網路與主機位元組轉換函式:htons ntohs htonl ntohl (s 就是short l是long h是host n是network)

htons 把unsigned short型別從主機序轉換到網路序,htonl 把unsigned long型別從主機序轉換到網路序,ntohs 把unsigned short型別從網路序轉換到主機序,ntohl 把unsigned long型別從網路序轉換到主機序。

在使用little endian的系統中 這些函式會把位元組序進行轉換 在使用big endian型別的系統中這些函式會定義成空巨集。

將用點分割的ip位址轉換位乙個in_addr結構的位址,這個結構的定義見筆記(一),實際上就是乙個unsigned long值。計算機內部處理ip位址可是不認識如192.1.8.84之類的資料。  

unsigned long inet_addr( const char far * cp );

舉例:inet_addr("192.1.8.84")=1409810880

inet_addr("127.0.0.1")= 16777343

如果發生錯誤,函式返回inaddr_none值。

將網路位址轉換位用點分割的ip位址,是上面函式的逆函式。  

char far * inet_ntoa( struct in_addr in );

舉例:char * ipaddr=null;

char addr[20];

in_addr inaddr;

inaddr. s_addr=16777343;

ipaddr= inet_ntoa(inaddr);

strcpy(addr,ipaddr);  

這樣addr的值就變為127.0.0.1。

注意不要修改返回值或者進行釋放動作,如果函式失敗就會返回null值。

大尾端 小尾端和 htons函式

提到體系結構時,經常遇到大小尾端的概念,這裡做個總結。big endian 大尾端,也稱大端 高位 優先儲存。little endian 小尾端,也稱小端 低位 優先儲存。如下00000000 00000000 00000000 00000001的儲存 大尾端 00000000 00000000 0...

NAND FLASH大頁和小頁的區別

nand flash有兩類 大頁的nand和小頁的nand。每種nand的一頁中都有資料段 datafield 和附加段 spare field datafield用於存放資料用的,spare field 讀寫操作的時候存放校驗碼用的,大頁的nand中資料段2048b 附加段64b 小頁的nand中...

OLAP 大表和小表並行hash join

乙個表50mb 乙個表10gb 50m表做驅動表,放在pga裡 這時候慢在對對 10g 的全表掃瞄 對10個g掃瞄塊 需要開並行 我有這樣乙個演算法 乙個程序 讀 50mb 8程序 來 掃瞄 10gb 乙個 程序掃瞄 1.25gb 50mb 都分發到 8個程序 超大表和小表之間做hash join,...