為什么是這樣?
請大家思考一個(gè)問題:
現(xiàn)在有一個(gè)整數(shù):0x12345678,把它放在一個(gè)4字節(jié)的整型變量中,那第一個(gè)字節(jié)里面存放的是什么?是0x12還是0x78?
這其實(shí)就引出了計(jì)算機(jī)中存放數(shù)據(jù)的兩種方式:大端模式和小端模式。

在大端模式中,高位的數(shù)據(jù)存放在低地址,比如上面那個(gè)整數(shù)中,12表示的是整數(shù)的高位,那它存放在一開始的位置(低地址),如此一來,在大端模式下,內(nèi)存存放順序和我們書寫這個(gè)整數(shù)的順序是一致的。
而小端模式下,則剛好反過來,存放的順序和我們書寫的順序相反。
有一道經(jīng)常出現(xiàn)在各種筆試面試中的題目:如何判斷當(dāng)前計(jì)算機(jī)是大端模式還是小端模式。
知道了大端和小端的區(qū)別,相信你將能看懂下面這個(gè)答案:
#include?
int?main?()
{
??unsigned?int?x?=?0x12345678;
??char?*c?=?(char*)&x;
??if?(*c?==?0x78)?{
????printf("Little?endian");
??}?else?{
????printf("Big?endian");
??}
??return?0;
}
有的計(jì)算機(jī)使用大端,有的計(jì)算機(jī)使用小端,那他們怎么通信啊,不得出問題?
網(wǎng)絡(luò)的發(fā)明人們當(dāng)然也想到了這個(gè)問題,所以在RFC1700中規(guī)定,在網(wǎng)絡(luò)通信中一律使用大端模式。
比如在TCP中,端口是2個(gè)字節(jié),對于Web服務(wù)端80端口,我們用十六進(jìn)制書寫是:0x0050,在網(wǎng)絡(luò)中使用大端模式,數(shù)據(jù)和我們書寫順序一致,也是 00 50

但如果你在程序中查看卻發(fā)現(xiàn)是反過來的:

這是因?yàn)槲覀冸娔Xx86架構(gòu)使用的是小端模式。
最近,知識星球的第二期學(xué)習(xí)活動:手寫一個(gè)抓包軟件,正在火熱進(jìn)行當(dāng)中,在處理pcap數(shù)據(jù)包文件過程中,很多小伙伴兒都被這個(gè)字節(jié)序問題搞得暈頭轉(zhuǎn)向。
不過活動進(jìn)行到了第七天,大家還是一路堅(jiān)持了過來,而且堅(jiān)持的人數(shù)比去上次手寫一個(gè)Web服務(wù)器多了不少:

第1天:學(xué)習(xí)二進(jìn)制文件基本讀寫操作
第2天:學(xué)習(xí)內(nèi)存映射文件操作
第3天:pcap文件格式學(xué)習(xí)
第4-5天:pcap文件解析
第6天:解析以太網(wǎng)協(xié)議
第7天:解析IP協(xié)議報(bào)文
······
大家用著不同的編程語言,有C、C++、Python、Java、Go···去實(shí)現(xiàn)同一個(gè)功能,隨著一點(diǎn)點(diǎn)迭代,一點(diǎn)點(diǎn)完善,去完成自己的一個(gè)抓包軟件,在這個(gè)過程中一邊學(xué)習(xí)編程,一邊學(xué)習(xí)網(wǎng)絡(luò),是一次難得的綜合實(shí)踐,這比單純的看書看視頻學(xué)習(xí)要扎實(shí)深刻的多。
給大家看看幾位優(yōu)秀同學(xué)的代碼:
C++版本的:

C#版本的:

Python版本的:

Go語言版本的:

與優(yōu)秀的人一起同行,才能走的更快更穩(wěn),歡迎大家加入進(jìn)來,一起來一場計(jì)算機(jī)網(wǎng)絡(luò)和計(jì)算機(jī)編程的冒險(xiǎn)之旅!
