今天我們談談計算機中的大端小端以及網(wǎng)絡中的大端小端。參考了網(wǎng)上好多資料以后,從眾多資料中我也按照自己的理解方式,總結(jié)一下。
學習一個新東西:我們依然是先了解一下大端小端的歷史:
講故事 這個就需要求救一下度娘,以下故事來自度娘,真假我也不知道,權(quán)當聽故事:
“大端”和“小端”可以追溯到1726年的Jonathan Swift的《格列佛游記》,其中一篇講到有兩個國家因為吃雞蛋究竟是先打破較大的一端還是先打破較小的一端而爭執(zhí)不休,甚至爆發(fā)了戰(zhàn)爭。1981年10月,Danny Cohen的文章《論圣戰(zhàn)以及對和平的祈禱》(On holy wars and a plea for peace)將這一對詞語引入了計算機界。這么看來,所謂大端和小端,也就是big-endian和little-endian,其實是從描述雞蛋的部位而引申到計算機地址的描述,也可以說,是從一個俚語衍化來的計算機術(shù)語。稍有些英語常識的人都會知道,如果單靠字面意思來理解俚語,那是很難猜到它的正確含義的。在計算機里,對于地址的描述,很少用“大”和“小”來形容;對應地,用的更多的是“高”和“低”;很不幸地,這對術(shù)語直接按字面翻譯過來就成了“大端”和“小端”,讓人產(chǎn)生迷惑也不是很奇怪的事了。
聽完了故事,這下讓我們來看什么是大端小端:依然沿襲過去用圖講解,來理解結(jié)構(gòu):
現(xiàn)實生活中我們寫的數(shù)據(jù)時左邊位權(quán)高,右邊的位權(quán)低,比如123,1表示的就是100,對吧,因為計算機只認識0和1,這里,我把它換算成2進制形式:上圖是1的二進制形式。這下就要引出今天我們的主角大端小端,most significant (最高有效位)在低地址位就是大端,(least significat) 在高地址位就是小端,現(xiàn)在我們大多數(shù)的計算機都是采用八位一個字節(jié),所以當如果把1按照第一個存儲的話就是大端,第二個就是小端。上邊用紅色標記起來的就是理解的重點。
還有就是關(guān)于字符串是怎么區(qū)分的,比如說:char *ch ="12345",對于字符串,是沒有什么大端小端的,5一定是在高地址存放的。
可能上面的內(nèi)容你已經(jīng)搞清楚了,但是當你看一些關(guān)于網(wǎng)絡或者的資料時發(fā)現(xiàn)又有什么網(wǎng)絡字節(jié)序神馬的,然后又糊涂了,讓我們一起來破除關(guān)于網(wǎng)絡字節(jié)序列這些神馬的浮云。
了解網(wǎng)絡是怎樣發(fā)送數(shù)據(jù)的?
我們使用的網(wǎng)絡協(xié)議很多都是基于socket的,所以我們基于socket來講,在socket規(guī)范中發(fā)送數(shù)據(jù)是 這個方法
send(Socket soc, char * buf, len , 0);
第一個參數(shù)是對方的socket,也就是地址
第二個參數(shù)是 一個字符指針,也就是要發(fā)送的內(nèi)容存放的地址
第三個是發(fā)送數(shù)據(jù)的長度
第四個是和選擇協(xié)議相關(guān)的,一般設為0
所以這里我們看到在底層發(fā)送數(shù)據(jù)的方法里面根本沒有和什么大端小端有關(guān)系的東西,發(fā)送的函數(shù)只關(guān)心你要給老子發(fā)送的東西在哪兒,發(fā)多少,其他一概不管,好,現(xiàn)在用一個場景說明一下。程序員A把一個金額發(fā)給程序員B,這個金額是B欠A錢的金額。
//A發(fā)給B,這是B欠我A的數(shù)目 ,是1500元,下面是十六進制寫法
short a = 0x05DC;//于是A就
send(sock, (char *)&a,2,0);12341234
接收和發(fā)送的函數(shù)方法參數(shù)是一樣的
recv(Socket soc, char * buf, len , 0);
好,這個數(shù)目發(fā)完了,B接收的時候用下面的代碼
char ownMoney [2];recv(Socket soc,ownMoney, 2 , 0);1212
好了,數(shù)據(jù)發(fā)送和接受都完成了,到這里為止,和大小端半毛錢關(guān)系都沒有,接下來就有了。這B想看看到底欠了A多少錢了,用下面的代碼接收。
int total = ((ownMoney[0] << 8) | (ownMoney[1] & 0xFF ) &0xFF );11
一看嚇了一跳 56325,這就出大問題了,B心想,A是我鐵哥們兒,肯定不會騙我,肯定是那個地方數(shù)據(jù)出錯了,于是有了下面的對話
B:兄弟你電腦CPU是什么的?
A:是intel的啊
B:發(fā)送數(shù)據(jù)的時候有做什么處理嗎?
A:沒有做任何處理
B:額,我明白了
剛好B的機器也是Intel的CPU,B找到原因之后背了一遍我編寫的口訣,低地址是低位是小端,低低地址是高位為大端。
B分析了一下數(shù)據(jù)的發(fā)送流程,A發(fā)送兩個字節(jié)的short型數(shù)據(jù),因為A是小端所以,先發(fā)送過來的是低位數(shù)據(jù),后發(fā)送的是高位,我先接收的也是低位,后接收的是高位。
B修改程序后
int total = (ownMoney[0] &0xFF ) | ( (ownMoney[1] << 8) & 0xFF ) );11
一看,額,1500,心里松了一口氣,這就對了。我們來看看出現(xiàn)剛剛這個問題的原因。
A是 Intel CPU (小端機器), 0x05DC這個數(shù),低地址存放的是DC,高地址是05, B接受了放在 字符數(shù)組中, 因為B也是小端機器,B還原數(shù)據(jù)的時候是在低地址放在了高位,也就是0xDC,這是 不對的。
那總不能每次發(fā)送數(shù)據(jù)都問一下別人是什么CPU吧?
于是人們就約定將數(shù)據(jù)的低地址處放數(shù)據(jù)的高位(也叫大端法),于是A就遵循了這個約定, 發(fā)送之前將數(shù)據(jù)位置改了一下,因為之前低地址放的是低位。之前A的數(shù)據(jù)是這樣放的
低地址 | 高地址 |
---|---|
DC | 05 |
因為約定采用大端法發(fā)送數(shù)據(jù),所以要改成下面這樣
低地址 | 高地址 |
---|---|
05 | DC |
//這樣改變位置的代碼short a = 0x05DC;//用一個字符指針指向a char* pointerOfA = (char *)&a;//把數(shù)據(jù)的低位值保存在一個變量里,也就是 DCchar temp = *(pointerOfA );//把高位的值放在低位 *pointerOfA = *(pointerOfA +1);
*(pointerOfA +1) = temp;//再發(fā)送send(sock, pointerOfA ,2,0);1234567891011121312345678910111213
如果遵守約定,B就不用問A你的機器是什么類型了,但是還有一個問題,因為B的機器類型可能是大端也可能是小端,那接受數(shù)據(jù)的時候還要去判斷機器類型,這也太麻煩了,對,沒錯,底層的網(wǎng)絡處理就是這么麻煩。
以上總結(jié)是本人參考了網(wǎng)上的資料后自己整理發(fā)布的,如果原博主有問題,可以聯(lián)系本人。
另外有需要云服務器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。
網(wǎng)頁名稱:大端小端是什么?如何區(qū)分?-創(chuàng)新互聯(lián)
文章地址:http://muchs.cn/article28/ceejcp.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站收錄、關(guān)鍵詞優(yōu)化、響應式網(wǎng)站、網(wǎng)站建設、企業(yè)網(wǎng)站制作、自適應網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)