使用htons和ntohs進行位元組序轉換的理解

2021-10-24 12:27:32 字數 2837 閱讀 8669

uint16_t   value = 0xabcd;

uchar ch[2];

memcpy(ch,&value,sizeof(uint16_t);

(可以理解為高個的為排頭)

小結:memcpy是從低位元組開始拷貝,沒有問題,問題是cpu硬體的不同。 

htons:是主機位元組序轉成網路位元組序;

ntohs:是網路位元組序轉成主機位元組序;

由本文知,二者是同乙個巨集,可以通用,本質都是將位元組序顛倒。

網路位元組序是大端法排序

主機位元組序,則會根據cpu、作業系統的不同而不同,可能是大端排序,也可能是小端排序

倘若,通訊的兩端環境完全相同,通訊過程中,傳送端和接收端都可以不必進行位元組序轉換;

但是,如果通訊兩端環境不同,則必須要先統一位元組序,即通過htons或ntohs轉為大端序。

即:socketsend端,將該主機的uint16_t,uint32_t型別資料分別使用htons,htonl轉成大端排序,傳送到報文中,(如果主機實際是大端,呼叫函式,實際上沒操作,如果是小端,就給轉成大端);

uint16_t   send_value = 0xabcd; 

htons(send_value);

保證如上例中,使報文資料流是先存  0xab,後存0xcdsocketrecv端,收到的uint16_t,uint32_t型別的資料分別使用 ntohs,ntohl轉成該主機對應的位元組序形式(如果主機是大端,呼叫函式也不會轉換,結果為0xabcd,如果主機是小端,使用該函式會將資料顛倒位元組順序(將0xab和0xcd的順序調換,從而保證跟send端的資料保持一致)。

uchar ch[2]=;   

uint16_t  recv_value = *(uint16_t*)ch;

如果主機是大端序,則recv_value值為0xabcd;   //與傳送端的0xabcd匹配

如果主機是小端序,則recv_value值為0xcdab;   //與傳送端的0xabcd,不匹配

故需要使用ntohs函式,顛倒位元組順序

//報文資料

uchar ch[2]=;   

uint16_t  recv_value = *(uint16_t*)ch; //值為 0xabcd 或者 0xcdab

recv_value = ntohs(recv_value); //值為 0xabcd

除了使用:uint16_t  recv_value = *(uint16_t*)ch; 方式外,

可以使用mecpy(&recv_value,ch,sizeof(uint16_t));

小結:

1)使用htons能夠保證報文中的資料位元組順序跟實際書寫的資料位元組順序完全一致。如上,要傳的資料是0xabcd,使用htons後,報文中的一定是0xab,0xcd.

2)使用ntohs能夠保證 收到的資料跟 報文中的資料位元組順序完全一致。如上,報文中資料順序是0xab,0xcd,使用ntohs後,

收到的一定是0xabcd.

故為了方便移植,

send端:對於uint16_t 資料使用 htons , 對於uint32_t資料使用htonl;

recv端:對於uint16_t資料使用ntohs,對於uint32_t資料使用ntohl。

運用如上這兩部就能保證,傳送端與接收端的資料一致。

ps:在程式設計中,我們有時候會利用htons的特性,使資料儲存的陣列中兩個位元組與書寫順序相同。示例如下

需要注意的是:value_1,在經過htons(value)後,值發生了變化!!!!htons,ntohs二者是同乙個巨集,二者完全通用,其實質是如果主機序是小端,則位元組序顛倒,如果是大端,則不變。

因為int型資料,乙個資料佔多個位元組,所以會產生位元組序的問題,故需要呼叫htons,ntohs進行統一。

當資料時字串陣列,此時,報文資料就是乙個位元組,乙個位元組的存放,不存在位元組的問題,也不需要呼叫htons,ntohs進行轉換。

參考:

大尾端 小尾端和 htons函式

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

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

big endian 大尾端,也稱大端 高位 優先儲存。little endian 小尾端,也稱小端 低位 優先儲存。是按照高位位元組和地位位元組儲存的,不是位。如下00000000 00000000 00000000 00000001的儲存 大尾端 00000000 00000000 000000...

使用Spring Data JPA進行分頁和排序

概觀 在處理大量資料時,延遲處理通常是必不可少的。即使服務返回大量資料,消費者也不太可能使用它。考慮乙個購物 客戶在該 上搜尋產品,該 有數千種產品可供展示。獲取數千種產品並在網頁上顯示它們將非常耗時。在大多數情況下,客戶甚至可能不會檢視所有產品。對於這種情況,使用稱為分頁的技術。首先只顯示一小部分...