ntohs之類的位元組序轉換

2021-07-03 07:46:16 字數 2889 閱讀 1737

ntohs這種網路位元組序的函式是把位元組序從網路端轉換到主機端,使用時,可以忽略主機端的位元組序。

在做資料報的協議解析時,常常需要轉換資料報的長度,要使用這些函式做位元組轉換,但要注意轉換源的位元組序,如果是大端儲存則可以,但如果是小端儲存就無效,甚至出錯。(否則根據轉換後的數值做記憶體分配時會失敗的)

以下內容**:

或許你曾經仔細了解過什麼是大端小端,也動手編寫了測試手頭上的機器上是大端還是小端的程式,甚至還編寫了大端小端轉換程式;但過了一段時間之後,當你再看到大端和小端這兩個字眼,你的腦中很快浮起了自己曾經做過的工作,卻總是想不起究竟哪種是大端、哪種是小端,然後又去查以前寫的記錄?更讓人不快的是,這種經歷反反覆覆,讓你十分困擾。如果你和以前的筆者一樣,有過這種不快的經歷,那麼這篇文章希望能幫你徹底解決這個苦惱,讓你徹底記住它們。 

如果你在工作中經常使用到大端和小端以至於對它們十分熟悉,或者你的記憶力在保持時間的長度和精準度上都十分優秀,以至於不需要借助其他的方法,那麼這篇文章不適合你。

如果你在看這篇文章前完全不知道什麼是大端和小端,那麼可以參考本文的附錄或者其他的博文,相關的介紹非常之多,而附錄提供了乙個很常見解釋和一段測試程式,然後再來看正文。

為了幫助記憶,理解是必要的;而記憶的目的,也就是為什麼要記住它,是更重要的。

現在先來理解這對概念,大端和小端這兩個令人迷惑的術語究竟是如何產生的?《程式設計實踐》第9章中提到,「大端」和「小端」可以追溯到2023年的jonathan swift的《格列佛遊記》,其中一篇講到有兩個國家因為吃雞蛋究竟是先打破較大的一端還是先打破較小的一端而爭執不休,甚至爆發了戰爭。2023年10月,danny cohen的文章《論聖戰以及對和平的祈禱》(on holy wars and a plea for peace)將這一對詞語引入了計算機界。這麼看來,所謂大端和小端,也就是big-endian和little-endian,其實是從描述雞蛋的部位而引申到計算機位址的描述,也可以說,是從乙個俚語衍化來的計算機術語。稍有些英語常識的人都會知道,如果單靠字面意思來理解俚語,那是很難猜到它的正確含義的。在計算機裡,對於位址的描述,很少用「大」和「小」來形容;對應地,用的更多的是「高」和「低」;很不幸地,這對術語直接按字面翻譯過來就成了「大端」和「小端」,讓人產生迷惑也不是很奇怪的事了。

不過給我啟發的是,在裘宗燕翻譯的《程式設計實踐》裡,這對術語並沒有翻譯為「大端」和小端,而是「高尾端」和「低尾端」,這就好理解了:如果把乙個數看成乙個字串,比如11223344看成"11223344",末尾是個'\0','11'到'44'個占用乙個儲存單元,那麼它的尾端很顯然是44,前面的高還是低就表示尾端放在高位址還是低位址,它在記憶體中的放法非常直觀,如下圖:

「高/低尾端」比「大/小端」更不容易讓人迷惑。但是根據個人經驗,在市面上的書籍、網路上的各種資料中,很遺憾,前者已經很少見了,多見的是後者。好在這兩對形容詞中,恰好「高」和「大」對應,「低」和「小」對應;既然高尾端對應的是大端,低尾端對應的是小端,那麼當你再見到大端和小端這一對術語,就可以在腦中把它們轉化成高尾端和低尾端,這時憑著之前的理解,甚至不用回憶,想著高低的字面含義就能回想起它們的含義。但是很奇怪的是,同樣是裘宗燕翻譯的《程式設計原本》(elements of programming),卻把big-endian翻譯成大尾格式(第一章)。

理解之後,總結一下,記憶的方法是:

(資料看成字串)大端——高尾端,小端——低尾端

稍一思索什麼是「高」、什麼是"低","尾端"又是什麼,問題迎刃而解,再不用擔心被「大端」和「小端」迷惑。用這種方式,是時候放棄原先的死記硬背和容易把自己繞進去而發生迷惑的理解了。

附錄:什麼是「大端」和「小端」及一段測試本機大端還是小端的**

(這段文字是《unix網路程式設計·卷一》的關於這個概念的概括;不僅限於這本書,很多計算機書籍都是這麼介紹這個概念的,你會在和計算機相關不同領域的書中遇到它們。儘管很令人疑惑,但是在閱讀正文前,你最好對這兩個詞語的概念有所理解。當然,如果你以前向正文中描述的一樣接觸過它們,那就不必讀這一部分了。讀完後你會發現,你雖然理解了含義,但很容易忘掉,這時你就可以看正文部分了)

對於乙個由2個位元組組成的16位整數,在記憶體中儲存這兩個位元組有兩種方法:一種是將低序位元組儲存在起始位址,這稱為小端(little-endian)位元組序;另一種方法是將高序位元組儲存在起始位址,這稱為大端(big-endian)位元組序。

在圖中,頂部表明記憶體位址增長方向從右到左,在底部標明記憶體位址增長的方向為從左到右。並且還標明最高有效位(most significant bit,msb)是這個16位值最左邊一位,最低有效位(least significant bit, lsb)是這個16位值最右邊一位。術語「小端」和「大端」表示多個位元組值的哪一端(小端或大端)儲存在該值的起始位址。

這兩種位元組序沒有標準可循,都有系統在使用。把某個給定系統所用的位元組序稱為主機位元組序,可以用以下程式輸出主機位元組序。方法是在乙個短整數變數中存放2位元組的值0x0102,然後檢視它的連續位元組c[0](對應上圖位址a)和c[1](對應上圖位址a+1),以此確定位元組序。

#include #include 

int main(int argc, char **argv)

un;un.s = 0x0102

;

if(sizeof(short)==2

) else

printf(

"sizeof(short)= %d\n

",sizeof(short

)); exit(0);

}

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

uint16 t value 0xabcd uchar ch 2 memcpy ch,value,sizeof uint16 t 可以理解為高個的為排頭 小結 memcpy是從低位元組開始拷貝,沒有問題,問題是cpu硬體的不同。htons 是主機位元組序轉成網路位元組序 ntohs 是網路位元組序轉...

位元組序的轉換

提供一種位元組序轉換實現的思路。假使在一台64位的機器上定義的整數int val 0x01020304,轉換之後為0x04030201 big endian little endian跟多位元組型別的資料有關的比如int,short,long型,而對單位元組資料byte卻沒有影響。big endia...

由ntohs引出來的大小位元組序

ntohs net to host short int 16位 htons host to net short int 16位 ntohl net to host long int 32位 htonl host to net long int 32位 ntohs簡述 將乙個無符號短整形數從網路位元組...