1.字節(jié)序
字節(jié)序,又稱端序或尾序,指的是多字節(jié)數(shù)據(jù)在內(nèi)存中的存放順序。學(xué)過(guò)C語(yǔ)言后,我們知道一個(gè)int型變量a是占用4個(gè)字節(jié),假設(shè)它的起始地址也就是&a是0x10處,那么變量a的四個(gè)字節(jié)將會(huì)被存儲(chǔ)在0x10、0x11、0x12和0x13這四個(gè)字節(jié)位置上。
但是當(dāng)我們寫(xiě)好通信程序發(fā)送數(shù)據(jù)時(shí)候的時(shí)候,這個(gè)a變量通過(guò)TCP連接傳輸后收到的與發(fā)送的不一致,即有可能發(fā)過(guò)去的序列變成了0x12、0x13的值在前,0x10、0x11上的值在后,這樣組成的四個(gè)字節(jié)的int類型值肯定就不一樣了。
所以要引入大端和小端的概念。
2.大端和小端
計(jì)算機(jī)有兩種儲(chǔ)存數(shù)據(jù)的方式:大端字節(jié)序(Big Endian)和小端字節(jié)序(Little Endian)。
大端模式:是指數(shù)據(jù)的高字節(jié)保存在內(nèi)存的低地址中,低字節(jié)保存在內(nèi)存的高地址端。
小端模式:是指數(shù)據(jù)的高字節(jié)保存在內(nèi)存的高地址中,低字節(jié)保存在內(nèi)存的低地址端。
以一個(gè)兩字節(jié)short型變量0x0102的存儲(chǔ)舉例:
大端字節(jié)序:高位字節(jié)在前,低位字節(jié)在后,01|02,從左往右看著更習(xí)慣。
小端字節(jié)序:低位字節(jié)在前,高位字節(jié)在后,02|01,也存在這種存儲(chǔ)順序。
我們以0x12345678這個(gè)數(shù)字為例,它的大端模式和小端模式分別如下:
3.原因?
計(jì)算機(jī)處理字節(jié)序的時(shí)候,不知道什么是高位字節(jié),什么是低位字節(jié)。它只知道按順序讀取字節(jié),先讀第一個(gè)字節(jié),再讀第二個(gè)字節(jié)…
如果是大端字節(jié)序,先讀到的就是高位字節(jié),后讀到的就是低位字節(jié);小端字節(jié)序正好相反。
如果這樣,那統(tǒng)一用符合我們?nèi)祟愖x寫(xiě)習(xí)慣的大端序就好了呀,為何還要弄出個(gè)小端序了?
這是疑問(wèn)計(jì)算機(jī)電路先處理低位字節(jié),效率比較高,因?yàn)橛?jì)算都是從低位開(kāi)始的,所以計(jì)算機(jī)的內(nèi)部處理都是小端字節(jié)序。
但是人類還是習(xí)慣讀寫(xiě)大端字節(jié)序,所以除了計(jì)算機(jī)的內(nèi)部處理,其他的場(chǎng)合幾乎都是大端字節(jié)序,比如網(wǎng)絡(luò)傳輸和文件儲(chǔ)存。
4.網(wǎng)絡(luò)序和主機(jī)序
明白了大小端之后,網(wǎng)絡(luò)序和主機(jī)序也就好理解了,
網(wǎng)絡(luò)字節(jié)序:TCP/IP各層協(xié)議將字節(jié)序定義為Big Endian,即大端模式,TCP/IP協(xié)議中使用的字節(jié)序是大端序。
主機(jī)字節(jié)序:整數(shù)在內(nèi)存中存儲(chǔ)的順序,目前以Little Endian,即小端模式,比較普遍(不同的CPU有不同的字節(jié)序)。
C/C++語(yǔ)言編寫(xiě)的程序里數(shù)據(jù)存儲(chǔ)順序是跟編譯平臺(tái)所在的CPU相關(guān)的,而現(xiàn)在比較普遍的x86處理器是小端模式(Little Endian)。Java編寫(xiě)的程序則唯一采用Big Endian方式來(lái)存儲(chǔ)數(shù)據(jù)。
所以,如果你的C/C++程序通過(guò)Socket將變量a = 0x12345678的首地址傳遞給了Java程序,由于Java采取Big Endian方式存取數(shù)據(jù),很顯然,本地?cái)?shù)據(jù)沒(méi)問(wèn)題,傳過(guò)去就變成0x78563412,這就出問(wèn)題了。畢竟不是所有的客戶端和服務(wù)端都是同一種語(yǔ)言、同一種CPU。因此轉(zhuǎn)換的問(wèn)題就來(lái)了
5.如何轉(zhuǎn)換
為避免開(kāi)頭說(shuō)到的網(wǎng)絡(luò)通信中存在的問(wèn)題,我們可以在傳輸數(shù)據(jù)之前和接收數(shù)據(jù)之后對(duì)數(shù)據(jù)進(jìn)行相應(yīng)處理,也就是主機(jī)序和網(wǎng)絡(luò)序的轉(zhuǎn)換。
C/C++提供了相應(yīng)的函數(shù)接口,htons、htonl用于主機(jī)序轉(zhuǎn)換到網(wǎng)絡(luò)序,ntohl、ntohs用于網(wǎng)絡(luò)序轉(zhuǎn)換到主機(jī)序。
其中h表示host主機(jī),n表示network網(wǎng)絡(luò)。有興趣可以點(diǎn)擊閱讀
C語(yǔ)言網(wǎng)提供由在職研發(fā)工程師或ACM藍(lán)橋杯競(jìng)賽優(yōu)秀選手錄制的視頻教程,并配有習(xí)題和答疑,點(diǎn)擊了解:
一點(diǎn)編程也不會(huì)寫(xiě)的:零基礎(chǔ)C語(yǔ)言學(xué)練課程
解決困擾你多年的C語(yǔ)言疑難雜癥特性的C語(yǔ)言進(jìn)階課程
從零到寫(xiě)出一個(gè)爬蟲(chóng)的Python編程課程
只會(huì)語(yǔ)法寫(xiě)不出代碼?手把手帶你寫(xiě)100個(gè)編程真題的編程百練課程
信息學(xué)奧賽或C++選手的 必學(xué)C++課程
藍(lán)橋杯ACM、信息學(xué)奧賽的必學(xué)課程:算法競(jìng)賽課入門(mén)課程
手把手講解近五年真題的藍(lán)橋杯輔導(dǎo)課程