c 主機和網路位元組序的轉換

2021-09-09 04:57:55 字數 3124 閱讀 7621

最近使用c#進行網路開發,需要處理iso8583報文,由於其中有些域是數值型的,於是在傳輸的時候涉及到了位元組序的轉換。

位元組順序是指佔記憶體多於乙個位元組型別的資料在記憶體中的存放順序,通常有兩種位元組順序,根據他們所處的位置我們分別稱為主機節序和網路位元組序。

通常我們認為網路位元組序為標準順序,封包的時候,將主機位元組序轉換為網路位元組序,拆包的時候要將網路位元組序轉換為主機位元組序。

原以為還要自己寫函式,其實網路庫已經提供了。

主機到網路:short/int/long ipaddress.hosttonetworkorder(short/int/long)

網路到主機:short/int/long ipaddress.networktohostorder(short/int/long)

主機位元組序指低位元組資料存放在記憶體低位址處,高位元組資料存放在記憶體高位址處,如:

int x=1;    //此時x為主機位元組序:[1][0][0][0] 低位到高位

int y=65536 //此時y為主機位元組序:[0][0][1][0] 低位到高位

我們通過主機到網路位元組序的轉換函式分別對x和y進行轉換得到他們對應的網路位元組序值,

網路節序是高位元組資料存放在低位址處,低位元組資料存放在高位址處,如:

int m=ipaddress.hosttonetworkorder(x);

//此時m為主機位元組序:[0][0][0][1] 高位到低位

int n=ipaddress.hosttonetworkorder(y);

//此時n為主機位元組序:[0][1][0][0] 高位到低位

經過轉換以後,我們就可以通過

bytebtvalue=bitconverter.getbytes(m);

得到乙個長度為4的byte陣列,然後將這個陣列設定到報文的相應位置傳送出去即可。

同樣,收到報文後,可以將報文按域拆分,得到btvalue,使用

int m=bitconverter.toint32(btvalue,0);//從btvalue的第0位開始轉換

得到該域的值,此時還不能直接使用,應該再用網路到主機位元組序的轉換函式進行轉換:

int x=ipaddress.networktohostorder(m);

這時得到的x才是報文中的實際值。

ps:網路位元組序與主機位元組序

不同的cpu有不同的位元組序型別 這些位元組序是指整數在記憶體中儲存的順序 這個叫做主機序

最常見的有兩種

1. little endian:將低序位元組儲存在起始位址

2. big endian:將高序位元組儲存在起始位址

le little-endian

最符合人的思維的位元組序

位址低位儲存值的低位

位址高位儲存值的高位

怎麼講是最符合人的思維的位元組序,是因為從人的第一觀感來說

低位值小,就應該放在記憶體位址小的地方,也即記憶體位址低位

反之,高位值就應該放在記憶體位址大的地方,也即記憶體位址高位

be big-endian

最直觀的位元組序

位址低位儲存值的高位

位址高位儲存值的低位

為什麼說直觀,不要考慮對應關係

只需要把記憶體位址從左到右按照由低到高的順序寫出

把值按照通常的高位到低位的順序寫出

兩者對照,乙個位元組乙個位元組的填充進去

例子:在記憶體中雙字0x01020304(dword)的儲存方式

記憶體位址

4000 4001 4002 4003

le 04 03 02 01

be 01 02 03 04

例子:如果我們將0x1234abcd寫入到以0x0000開始的記憶體中,則結果為

big-endian   little-endian

0x0000   0x12       0xcd

0x0001   0x23       0xab

0x0002   0xab       0x34

0x0003   0xcd       0x12

x86系列cpu都是little-endian的位元組序.

網路位元組順序是tcp/ip中規定好的一種資料表示格式,它與具體的cpu型別、作業系統等無關,從而可以保證資料在不同主機之間傳輸時能夠被正確解釋。網路位元組順序採用big endian排序方式。

為了進行轉換 bsd socket提供了轉換的函式 有下面四個

htons 把unsigned short型別從主機序轉換到網路序

htonl 把unsigned long型別從主機序轉換到網路序

ntohs 把unsigned short型別從網路序轉換到主機序

ntohl 把unsigned long型別從網路序轉換到主機序

在使用little endian的系統中 這些函式會把位元組序進行轉換

在使用big endian型別的系統中 這些函式會定義成空巨集

同樣 在網路程式開發時 或是跨平台開發時 也應該注意保證只用一種位元組序 不然兩方的解釋不一樣就會產生bug.

注:1、網路與主機位元組轉換函式:htons ntohs htonl ntohl (s 就是short l是long h是host n是network)

2、不同的cpu上執行不同的作業系統,位元組序也是不同的,參見下表。

處理器     作業系統     位元組排序

alpha     全部     little endian

hp-pa     nt     little endian

hp-pa     unix     big endian

intelx86     全部     little endian <-----x86系統是小端位元組序系統

motorola680x()     全部     big endian

mips     nt     little endian

mips     unix     big endian

powerpc     nt     little endian

powerpc     非nt     big endian   <-----ppc系統是大端位元組序系統

rs/6000     unix     big endian

sparc     unix     big endian

ixp1200 arm核心     全部     little endian

主機位元組序和網路位元組序轉換

為什麼要轉換?主機位元組序 整數在記憶體中儲存的順序,不同的處理器對應不容的模式 little endian 將低序位元組儲存在起始位址 big endian 將高序位元組儲存在起始位址 網路位元組序 整數在網路中的傳送順序 網路位元組順序是tcp ip中規定好的一種資料表示格式,它與具體的cpu型...

網路位元組序與主機位元組序的轉換

在對ip位址結構體sockaddr in賦值的時候,經常會用到下列的函式htonl,htons,inet addr,與之相對應的函式是ntohl,ntohs,inet ntoa。檢視這些函式的解析,會發現這些函式其實是與主機位元組序和網路位元組序之間轉換有關。就是什麼網路位元組序,什麼是主機位元組序...

網路位元組序與主機位元組序的轉換

在對ip位址結構體sockaddr in賦值的時候,經常會用到下列的函式htonl,htons,inet addr,與之相對應的函式是ntohl,ntohs,inet ntoa。檢視這些函式的解析,會發現這些函式其實是與主機位元組序和網路位元組序之間轉換有關。就是什麼網路位元組序,什麼是主機位元組序...