日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

socket 大端 小端 转换 (转)《二》

發(fā)布時(shí)間:2025/5/22 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 socket 大端 小端 转换 (转)《二》 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

http://blog.csdn.net/kukumouse/article/details/2270356

(1)對于位域結(jié)構(gòu)中的變量來說,其長度不能跨越字節(jié),也就是說不能超過8位。當(dāng)然如果設(shè)置空白位(無名變量,僅僅用作占位的)是沒有這個(gè)限制的。如果一個(gè)字節(jié)剩下的位長度不夠一個(gè)位域,那么從下個(gè)字節(jié)開始,也可有意置某個(gè)位域從下個(gè)字節(jié)開始。例如:

struct bits4_5

{? //一個(gè)從到小的存放順序結(jié)構(gòu)體

?? unsigned : 10;? //從位15向下跳到位5

?? unsigned? bit5:1;

?? unsigned bit4:1;

};

例二:

struct xx

{

?? unsigned a:4;

?? unsigned :2;

?? unsigned b:4; // 從第二個(gè)字節(jié)開始

};

?

(2)不同的編譯器結(jié)構(gòu)存儲(chǔ)的方式不一樣相同,這個(gè)同不同的機(jī)器內(nèi)存中存放變量的字節(jié)序不同一個(gè)道理。我們知道,關(guān)于字節(jié)序有大端和小端之分。一般來說,Intel處理器使用的是小端(little endian),Moto處理器使用的是大端(記憶中好像就Intel的用小端,其它的基本上都是大端)。小端和大端的區(qū)別在于,內(nèi)存對于變量的存放規(guī)則不同。對于小端來說:低位字節(jié)存放在內(nèi)存中相對低地址;高位字節(jié)存放在內(nèi)存中相對高地址。示例如下:一個(gè)WORD32內(nèi)容的變量,占4個(gè)字節(jié):Byte3 Byte2 Byte1 Byte0,在內(nèi)容中存放:

?Base Address +0????? Byte0

Base Address +1????? Byte1

Base Address +2????? Byte2

Base Address +3????? Byte3

??? 類推,大端存放恰恰相反。這個(gè)主要在網(wǎng)絡(luò)處理中使用的比較多。因?yàn)榭蛻舳艘驗(yàn)槭艿讲煌奶幚砥飨拗?#xff0c;因?yàn)橐獙?shí)現(xiàn)不同機(jī)器間數(shù)據(jù)的傳遞正確性,要同一規(guī)則。我們在網(wǎng)絡(luò)中使用的是網(wǎng)絡(luò)字節(jié)序,也就是大端,所以網(wǎng)絡(luò)上發(fā)送字節(jié)序要注意,特別是建立socket時(shí)目的方的IP地址和Port的表示要進(jìn)行處理才行。可能有人會(huì)問及這里為什么名說到字節(jié)序卻沒有提及傳輸?shù)臄?shù)據(jù)。因?yàn)槲覀兇蟛糠侄际鞘褂米止?jié)流byte stream的TCP方式,所以不存在字節(jié)序問題。

??? 上面說的是字節(jié)序。除此之外,不同的編譯器存儲(chǔ)結(jié)構(gòu)(類)的方式也是不一樣的,有的是采用“從小到大的字節(jié)存儲(chǔ)順序”,有的是采用“從大到小的字節(jié)存儲(chǔ)順序”。例如下面的結(jié)構(gòu)定義:

????????????

struct bits4_5?? // 按照從小到大字節(jié)存儲(chǔ)順序

?????? {

?????????? unsigned :4; // 跳過位0—位3

?????????? unsigned bit4:1;

?????????? unsigned bit5:1;

};

struct bits4_5 // 按照從大到小字節(jié)存儲(chǔ)順序

{

?? unsigned:10;? // 從位15跳過10位至為6

?? unsigned bit5:1;

?? unsigned bit4:1;

}

下面看一個(gè)簡單的例子,主要是調(diào)試前后臺(tái)程序的時(shí)候發(fā)現(xiàn)的問題。當(dāng)時(shí)的環(huán)境為:前臺(tái)是跑在單板上的程序,其中單板上運(yùn)行的是VxWorks實(shí)時(shí)操作系統(tǒng);后臺(tái)的程序是運(yùn)行在PC機(jī)器上,前臺(tái)單板通過網(wǎng)口和后臺(tái)連在一個(gè)Hub上實(shí)現(xiàn)互通。

在后臺(tái)有結(jié)構(gòu)如下(為了不引起麻煩,修改了其中的變量名稱)typedef struct NetAddr

{

?? DWORD a:2;

?? DWORD b:2;

?? DWORD c:3;

?? DWORD d:1;

?? DWORD e:4;

?? DWORD f:4;

?? DWORD g:4;

?? DWORD h:4;

?? DWORD i:8;

}T_NetAddr;

typedef union VNetAddr

{? // 針對不同的平臺(tái)使用的地址不同

?? T_NetAddr tNetAddr;

?? DWORD dwAddr;

}T_VNetAddr;

在后臺(tái)中傳遞給前臺(tái),由于字節(jié)序不一樣,要進(jìn)行轉(zhuǎn)換,這里轉(zhuǎn)換就要求按照字節(jié)進(jìn)行調(diào)整了,這個(gè)這里就不說了,這里我們只是看看結(jié)構(gòu)體中位域的存放規(guī)則。這里我們的PC機(jī)器是按照小端進(jìn)行存放的。

在main里面我們?nèi)缦抡{(diào)用:

T_VNetAddr net;

?? net.tNetAddr.a=1;

?? net.tNetAddr.b=0;

?? net.tNetAddr.c=0;

?? net.tNetAddr.d=0;

?? net.tNetAddr.e=2;

?? net.tNetAddr.f=9;

?? net.tNetAddr.g=0;

?? net.tNetAddr.h=0;

?? net.tNetAddr.i=128;

我們可以觀察內(nèi)存中的net變量的值,各個(gè)位域的值如上面的賦值所示,存放的時(shí)候按照結(jié)構(gòu)體中定義的順序一個(gè)挨著一個(gè)順序存放(按照從小到大的地址存放順序,最前面定義的位域存放在低地址,后面定義的位域存放在高地址端):

???????????? b7 b6 b5? b4 b3 b2? b1 b0

第一個(gè)字節(jié): 0? 0? 0? 0? 0? 0? 0? 1???????? b1b0=01 對應(yīng)于位域a

第二個(gè)字節(jié)?? 1? 0? 0? 1? 0? 0? 1? 0??? b7b6b5b4=9 對應(yīng)于位域f? b3b2b1b0=2對應(yīng)e

第三個(gè)字節(jié)?? 0? 0? 0? 0? 0? 0? 0? 0

第四個(gè)字節(jié)?? 1? 0? 0? 0? 0? 0? 0? 0? b7b6b5b4b3b2b1b0=128對應(yīng)于i=128

這樣看就比較清晰了,如果我們查看一下net.dwAddr就會(huì)發(fā)現(xiàn)其值為0x80009201,為什么吶?

結(jié)構(gòu)體存放內(nèi)部位域的順序是按照小端,前面定義的位域存放在低地址,這樣依次從前到后存放的地址是由低向高的存放。讀取DWORD類型的變量的時(shí)候,按照小端,地位字節(jié)存放在低地址,高位字節(jié)存放在高地址的規(guī)則,DWORD類型的dwAddr的字節(jié)排列如下:

第四個(gè)字節(jié)??? 第三個(gè)字節(jié)??? 第二個(gè)字節(jié)?? 第一個(gè)字節(jié)

80????????????? 00??????????? 92??????????? 01

沒有問題!!!

注意:千萬不要誤以為是:01920080(從前往后讀)。

-------------------------------------------------------

最近看到網(wǎng)上的一篇文章,寫的是關(guān)于大端小端互相轉(zhuǎn)換的問題。其中定義了這樣一個(gè)宏
#define sw16(x) \
? ? ((short)( \
? ?? ???(((short)(x) & (short)0x00ffU) << 8 ) | \
? ?? ???(((short)(x) & (short)0xff00U) >> 8 ) ))
這里實(shí)現(xiàn)的是一個(gè)交換兩個(gè)字節(jié)順序。
不知哪位能解釋一下這個(gè),小弟實(shí)在是看不懂。先謝謝了!

--------

假設(shè)x=0xaabb
(short)(x) & (short)0x00ffU) 與將16位數(shù)高8位置0? ?成了0x00bb 然后<<8 向左移8位后 低8位變成了高8位 低8位補(bǔ)0??結(jié)果為 0xbb00
(((short)(x) & (short)0xff00U) >> 8 ) )) 恰好相反 得到的結(jié)果為 0x00aa
兩個(gè)結(jié)果再 或一下 0xbb00 | 0x00aa 就成了 0xbbaa

------------------------------------------------------------

在網(wǎng)絡(luò)傳輸時(shí),將long類型先轉(zhuǎn)化為byte數(shù)組,步驟如下:

?

long l;

byte[] b;

b[0]=(byte)(l>>>24);

b[1]]=(byte)(l>>>16);

b[2]]=(byte)(l>>>8);

b[3]]=(byte)(l);

此時(shí),b[]中就按照網(wǎng)絡(luò)字節(jié)順序(大端法,即l的高位數(shù)據(jù)存放在byte[]的低位地址,因?yàn)榈刂肥?/strong> 從低向高發(fā)展的)存放著4個(gè)bytes的數(shù)據(jù) 使用OutputStream的public void write(byte[]?b,int?off,int?len)方法來向Socket寫字節(jié)流 ,寫byte[0]至byte[3]的字節(jié)。

?

java.io
Class OutputStream

write

public abstract void write(int?b)throws IOException
Writes the specified byte to this output stream. The general contract for write is that one byte is written to the output stream. The byte to be written is the eight low-order bits of the argument b. The 24 high-order bits of bare ignored.

Subclasses of OutputStream must provide an implementation for this method.

?

Parameters:
b - the byte.
Throws:
IOException - if an I/O error occurs. In particular, an IOException may be thrown if the output stream has been closed.

write

public void write(byte[]?b,int?off,int?len)throws IOException
Writes len bytes from the specified byte array starting at offset off to this output stream. The general contract for write(b, off, len) is that some of the bytes in the array b are written to the output stream in order; element b[off] is the first byte written and b[off+len-1]is the last byte written by this operation.

The write method of OutputStream calls the write method of one argument on each of the bytes to be written out. Subclasses are encouraged to override this method and provide a more efficient implementation.

If b is null, a NullPointerException is thrown.

If off is negative, or len is negative, or off+len is greater than the length of the array b, then an IndexOutOfBoundsException is thrown.

?

Parameters:
b- the data.
off- the start offset in the data.
len- the number of bytes to write.
Throws:
IOException - if an I/O error occurs. In particular, an IOException is thrown if the output stream is closed.

------關(guān)于網(wǎng)絡(luò)、主機(jī)字節(jié)順序的文章

http://www-128.ibm.com/developerworks/cn/java/l-datanet/index.html

?

主機(jī)和網(wǎng)絡(luò)字節(jié)序的轉(zhuǎn)換

最近使用C#進(jìn)行網(wǎng)絡(luò)開發(fā),需要處理ISO8583報(bào)文,由于其中有些域是數(shù)值型的,于是在傳輸?shù)臅r(shí)候涉及到了字節(jié)序的轉(zhuǎn)換。字節(jié)順序是指占內(nèi)存多于一個(gè)字節(jié)類型的數(shù)據(jù)在內(nèi)存中的存放順序,通常有兩種字節(jié)順序,根據(jù)他們所處的位置我們分別稱為主機(jī)節(jié)序和網(wǎng)絡(luò)字節(jié)序。

通常我們認(rèn)為網(wǎng)絡(luò)字節(jié)序?yàn)闃?biāo)準(zhǔn)順序,封包的時(shí)候,將主機(jī)字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序,拆包的時(shí)候要將網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換為主機(jī)字節(jié)序。原以為還要自己寫函數(shù),其實(shí)網(wǎng)絡(luò)庫已經(jīng)提供了。

主機(jī)到網(wǎng)絡(luò):short/int/long IPAddress.HostToNetworkOrder(short/int/long)

網(wǎng)絡(luò)到主機(jī):short/int/long IPAddress.NetworkToHostOrder(short/int/long)

?

主機(jī)字節(jié)序指低字節(jié)數(shù)據(jù)存放在內(nèi)存低地址處,高字節(jié)數(shù)據(jù)存放在內(nèi)存高地址處,如:

int x=1;? ? //此時(shí)x為主機(jī)字節(jié)序:[1][0][0][0] 低位到高位

int y=65536 //此時(shí)y為主機(jī)字節(jié)序:[0][0][1][0] 低位到高位

我們通過主機(jī)到網(wǎng)絡(luò)字節(jié)序的轉(zhuǎn)換函數(shù)分別對x和y進(jìn)行轉(zhuǎn)換得到他們對應(yīng)的網(wǎng)絡(luò)字節(jié)序值,網(wǎng)絡(luò)節(jié)序是高字節(jié)數(shù)據(jù)存放在低地址處,低字節(jié)數(shù)據(jù)存放在高地址處,如:

int m=IPAddress.HostToNetworkOrder(x);

//此時(shí)m為主機(jī)字節(jié)序:[0][0][0][1] 高位到低位

int n=IPAddress.HostToNetworkOrder(y);

//此時(shí)n為主機(jī)字節(jié)序:[0][1][0][0] 高位到低位

?

經(jīng)過轉(zhuǎn)換以后,我們就可以通過

byte[]btValue=BitConverter.GetBytes(m);

得到一個(gè)長度為4的byte數(shù)組,然后將這個(gè)數(shù)組設(shè)置到報(bào)文的相應(yīng)位置發(fā)送出去即可。

同樣,收到報(bào)文后,可以將報(bào)文按域拆分,得到btValue,使用

int m=BitConverter.ToInt32(btValue,0);//從btValue的第0位開始轉(zhuǎn)換

得到該域的值,此時(shí)還不能直接使用,應(yīng)該再用網(wǎng)絡(luò)到主機(jī)字節(jié)序的轉(zhuǎn)換函數(shù)進(jìn)行轉(zhuǎn)換:

int x=IPAddress.NetworkToHostOrder(m);

這時(shí)得到的x才是報(bào)文中的實(shí)際值。

?

?

?

---------------------------------------------------

也談字節(jié)序問題

http://bigwhite.blogbus.com/logs/2005/09/

一次Sun SPARC到Intel X86的平臺(tái)移植讓我們的程序遭遇了“字節(jié)序問題”,既然遇到了也就不妨深入的學(xué)習(xí)一下。

一、字節(jié)序定義
字節(jié)序,顧名思義字節(jié)的順序,再多說兩句就是大于一個(gè)字節(jié)類型的數(shù)據(jù)在內(nèi)存中的存放順序(一個(gè)字節(jié)的數(shù)據(jù)當(dāng)然就無需談順序的問題了)。

其實(shí)大部分人在實(shí)際的開發(fā)中都很少會(huì)直接和字節(jié)序打交道。唯有在跨平臺(tái)以及網(wǎng)絡(luò)程序中字節(jié)序才是一個(gè)應(yīng)該被考慮的問題。

在所有的介紹字節(jié)序的文章中都會(huì)提到字節(jié)序分為兩類:Big-Endian和Little-Endian。引用標(biāo)準(zhǔn)的Big-Endian和Little-Endian的定義如下:
a) Little-Endian就是低位字節(jié)排放在內(nèi)存的低地址端,高位字節(jié)排放在內(nèi)存的高地址端。
b) Big-Endian就是高位字節(jié)排放在內(nèi)存的低地址端,低位字節(jié)排放在內(nèi)存的高地址端。
c) 網(wǎng)絡(luò)字節(jié)序:TCP/IP各層協(xié)議將字節(jié)序定義為Big-Endian,因此TCP/IP協(xié)議中使用的字節(jié)序通常稱之為網(wǎng)絡(luò)字節(jié)序。

其實(shí)我在第一次看到這個(gè)定義時(shí)就很糊涂,看了幾個(gè)例子后也很是朦朧。什么高/低地址端?又什么高低位?翻閱了一些資料后略有心得。

二、高/低地址與高低字節(jié)
首先我們要知道我們C程序映像中內(nèi)存的空間布局情況:在《C專家編程》中或者《Unix環(huán)境高級(jí)編程》中有關(guān)于內(nèi)存空間布局情況的說明,大致如下圖:
----------------------- 最高內(nèi)存地址 0xffffffff
?|?棧底
?.
?.????????????? 棧
?.
??棧頂
-----------------------
?|
?|
/|/

NULL (空洞)?

/|/
?|
?|
-----------------------
??????????????? 堆
-----------------------
未初始化的數(shù)據(jù)
----------------(統(tǒng)稱數(shù)據(jù)段)
初始化的數(shù)據(jù)
-----------------------
正文段(代碼段)
----------------------- 最低內(nèi)存地址 0x00000000

以上圖為例如果我們在棧上分配一個(gè)unsigned char buf[4],那么這個(gè)數(shù)組變量在棧上是如何布局的呢[注1]?看下圖:
棧底 (高地址)
----------
buf[3]
buf[2]
buf[1]
buf[0]
----------
棧頂 (低地址)

現(xiàn)在我們弄清了高低地址,接著我來弄清高/低字節(jié),如果我們有一個(gè)32位無符號(hào)整型0x12345678(呵呵,恰好是把上面的那4個(gè)字節(jié)buf看成一個(gè)整型),那么高位是什么,低位又是什么呢?其實(shí)很簡單。在十進(jìn)制中我們都說靠左邊的是高位,靠右邊的是低位,在其他進(jìn)制也是如此。就拿 0x12345678來說,從高位到低位的字節(jié)依次是0x12、0x34、0x56和0x78。

高低地址和高低字節(jié)都弄清了。我們再來回顧一下Big-Endian和Little-Endian的定義,并用圖示說明兩種字節(jié)序:
以unsigned int value = 0x12345678為例,分別看看在兩種字節(jié)序下其存儲(chǔ)情況,我們可以用unsigned char buf[4]來表示value:
Big-Endian: 低地址存放高位,如下圖:
棧底 (高地址)
---------------
buf[3] (0x78) -- 低位
buf[2] (0x56)
buf[1] (0x34)
buf[0] (0x12) -- 高位
---------------
棧頂 (低地址)

Little-Endian: 低地址存放低位,如下圖:
棧底 (高地址)
---------------
buf[3] (0x12) -- 高位
buf[2] (0x34)
buf[1] (0x56)
buf[0] (0x78) -- 低位
---------------
棧頂 (低地址)

在現(xiàn)有的平臺(tái)上Intel的X86采用的是Little-Endian,而像Sun的SPARC采用的就是Big-Endian。

三、例子
測試平臺(tái): Sun SPARC Solaris 9和Intel X86 Solaris 9
我們的例子是這樣的:在使用不同字節(jié)序的平臺(tái)上使用相同的程序讀取同一個(gè)二進(jìn)制文件的內(nèi)容。
生成二進(jìn)制文件的程序如下:
/* gen_binary.c */
int main() {
??????? FILE??? *fp = NULL;
??????? int???? value = 0x12345678;
??????? int???? rv = 0;

??????? fp = fopen("temp.dat", "wb");
??????? if (fp == NULL) {
??????????????? printf("fopen error/n");
??????????????? return -1;
??????? }

??????? rv = fwrite(&value, sizeof(value), 1, fp);
??????? if (rv != 1) {
??????????????? printf("fwrite error/n");
??????????????? return -1;
??????? }

??????? fclose(fp);
??????? return 0;
}

讀取二進(jìn)制文件的程序如下:
int main() {
??????? int???????????? value?? = 0;
??????? FILE?????????*fp???? = NULL;
??????? int???????????? rv????? = 0;
??????? unsigned??????? char buf[4];

??????? fp = fopen("temp.dat", "rb");
??????? if (fp == NULL) {
??????????????? printf("fopen error/n");
??????????????? return -1;
??????? }

??????? rv = fread(buf, sizeof(unsigned char), 4, fp);
??????? if (rv != 4) {
??????????????? printf("fread error/n");
??????????????? return -1;
??????? }

??????? memcpy(&value, buf, 4); // or value = *((int*)buf);
??????? printf("the value is %x/n", value);

??????? fclose(fp);
??????? return 0;
}

測試過程:
(1) 在SPARC平臺(tái)下生成temp.dat文件
在SPARC平臺(tái)下讀取temp.dat文件的結(jié)果:
the value is 12345678

在X86平臺(tái)下讀取temp.dat文件的結(jié)果:
the value is 78563412

(1) 在X86平臺(tái)下生成temp.dat文件
在SPARC平臺(tái)下讀取temp.dat文件的結(jié)果:
the value is 78563412

在X86平臺(tái)下讀取temp.dat文件的結(jié)果:
the value is 12345678

[注1]
buf[4]在棧的布局我也是通過例子程序得到的:
int main() {
??????? unsigned char buf[4];

??????? printf("the buf[0] addr is %x/n", buf);
??????? printf("the buf[1] addr is %x/n", &buf[1]);

??????? return 0;
}
output:
SPARC平臺(tái):
the buf[0] addr is ffbff788
the buf[1] addr is ffbff789
X86平臺(tái):
the buf[0] addr is 8047ae4
the buf[1] addr is 8047ae5

兩個(gè)平臺(tái)都是buf[x]所在地址高于buf[y] (x > y)。

----------------------------------------------------

一、大端模式&小端模式

所謂的“大端模式”,是指數(shù)據(jù)的低位(就是權(quán)值較小的后面那幾位)保存在內(nèi)存的高地址中,而數(shù)據(jù)的高位,保存在內(nèi)存的低地址中,這樣的存儲(chǔ)模式有點(diǎn)兒類似于把數(shù)據(jù)當(dāng)作字符串順序處理:地址由小向大增加,而數(shù)據(jù)從高位往低位放;

所謂的“小端模式”,是指數(shù)據(jù)的低位保存在內(nèi)存的低地址中,而數(shù)據(jù)的高位保存在內(nèi)存的高地址中,這種存儲(chǔ)模式將地址的高低和數(shù)據(jù)位權(quán)有效地結(jié)合起來,高地址部分權(quán)值高,低地址部分權(quán)值低,和我們的邏輯方法一致。

如果將一個(gè)32位的整數(shù)0x12345678 存放到一個(gè)整型變量(int)中,這個(gè)整型變量采用大端或者小端模式在內(nèi)存中的存儲(chǔ)由下表所示。為簡單起見,本文使用OP0表示一個(gè)32位數(shù)據(jù)的最高字節(jié)MSB(Most Significant Byte),使用OP3表示一個(gè)32位數(shù)據(jù)最低字節(jié)LSB(Least Significant Byte)。??

地址偏移??????? 大端模式?????? 小端模式
0x00?????????? 12(OP0)????? 78(OP3)
0x01?????????? 34(OP1)????? 56(OP2)
0x02?????????? 56(OP2)????? 34(OP1)
0x03?????????? 78(OP3)????? 12(OP0)


小端:較高的有效字節(jié)存放在較高的存儲(chǔ)器地址,較低的有效字節(jié)存放在較低的存儲(chǔ)器地址。
大端:較高的有效字節(jié)存放在較低的存儲(chǔ)器地址,較低的有效字節(jié)存放在較高的存儲(chǔ)器地址。

采用大小模式對數(shù)據(jù)進(jìn)行存放的主要區(qū)別在于在存放的字節(jié)順序,大端方式將高位存放在低地址,小端方式將高位存放在高地址。采用大端方式進(jìn)行數(shù)據(jù)存放符合人類的正常思維,而采用小端方式進(jìn)行數(shù)據(jù)存放利于計(jì)算機(jī)處理。到目前為止,采用大端或者小端進(jìn)行數(shù)據(jù)存放,其孰優(yōu)孰劣也沒有定論。

下面這段代碼可以用來測試一下你的編譯器是大端模式還是小端模式:

short int x;
char x0,x1;
x=0x1122;
x0=((char*)&x)[0]; //低地址單元
x1=((char*)&x)[1]; //高地址單元
若x0=0x11,則是大端; 若x0=0x22,則是小端......
上面的程序還可以看出,數(shù)據(jù)尋址時(shí),用的是低位字節(jié)的地址

二、主機(jī)序&網(wǎng)絡(luò)序

不同的 CPU 有不同的字節(jié)序類型這些字節(jié)序是指整數(shù)在內(nèi)存中保存的順序這個(gè)叫做主機(jī)序,最常見的有兩種:
1、Little endian :將低序字節(jié)存儲(chǔ)在起始地址
2、Big endian :將高序字節(jié)存儲(chǔ)在起始地址

網(wǎng)絡(luò)字節(jié)順序是TCP/IP中規(guī)定好的一種數(shù)據(jù)表示格式,它與具體的CPU類型、操作系統(tǒng)等無關(guān),從而可以保證數(shù)據(jù)在不同主機(jī)之間傳輸時(shí)能夠被正確解釋。網(wǎng)絡(luò)字節(jié)順序采用big endian排序方式。

為了進(jìn)行轉(zhuǎn)換 bsd socket提供了轉(zhuǎn)換的函數(shù) 有下面四個(gè):
htons 把unsigned short類型從主機(jī)序轉(zhuǎn)換到網(wǎng)絡(luò)序
htonl 把unsigned long類型從主機(jī)序轉(zhuǎn)換到網(wǎng)絡(luò)序
ntohs 把unsigned short類型從網(wǎng)絡(luò)序轉(zhuǎn)換到主機(jī)序
ntohl 把unsigned long類型從網(wǎng)絡(luò)序轉(zhuǎn)換到主機(jī)序

在使用little endian的系統(tǒng)中,這些函數(shù)會(huì)把字節(jié)序進(jìn)行轉(zhuǎn)換
在使用big endian類型的系統(tǒng)中,這些函數(shù)會(huì)定義成空宏

同樣,在網(wǎng)絡(luò)程序開發(fā)時(shí),或是跨平臺(tái)開發(fā)時(shí),也應(yīng)該注意保證只用一種字節(jié)序,不然兩方的解釋不一樣就會(huì)產(chǎn)生BUG。

注:
1、網(wǎng)絡(luò)與主機(jī)字節(jié)轉(zhuǎn)換函數(shù):htons ntohs htonl ntohl (s 就是short l是long h是host n是network)
2、不同的CPU上運(yùn)行不同的操作系統(tǒng),字節(jié)序也是不同的,參見下表:


處理器???????????? 操作系統(tǒng)???? 字節(jié)排序
Alpha?????????????????? 全部????? Little endian
HP-PA??????????????????? NT?????? Little endian
HP-PA?????????????????? UNIX???? Big endian
Intelx86??????????????? 全部???? Little endian <-----x86系統(tǒng)是小端字節(jié)序系統(tǒng)
Motorola680x()????????? 全部??? Big endian
MIPS???????????????????? NT?????? Little endian
MIPS??????????????????? UNIX??? Big endian
PowerPC????????????????? NT???? Little endian
PowerPC???????????????? 非NT??? Big endian?? <-----PPC系統(tǒng)是大端字節(jié)序系統(tǒng)
RS/6000???????????????? UNIX??? Big endian
SPARC?????????????????? UNIX??? Big endian
IXP1200 ARM核心???????? 全部????? Little endian

下面是一個(gè)檢驗(yàn)本機(jī)字節(jié)序的簡便方法:

//判斷本機(jī)的字節(jié)序
//返回true表為小段序。返回false表示為大段序
bool am_little_endian ()
{
unsigned short i=1;
return (int)*((char *)(&i)) ? true : false;
}
int main()
{
?? if(am_little_endian())
{
???????? ?? printf("本機(jī)字節(jié)序?yàn)樾《涡?\n");
}
else
{
????????? printf("本機(jī)字節(jié)序?yàn)榇蠖涡?\n");
}
??????? return 0;
}

三、入棧地址高低問題

堆棧是在內(nèi)存中指定的一段特殊存儲(chǔ)區(qū),存起始單元的地址叫棧底,當(dāng)前存儲(chǔ)單元地址叫棧頂,堆棧存儲(chǔ)區(qū)一旦指定,棧底就固定不變了,而棧頂是隨入棧、出棧操作呈動(dòng)態(tài)。而不同機(jī)型的堆棧設(shè)計(jì),有兩種情況:一是每入棧一個(gè)數(shù),棧頂?shù)刂芳?,每出棧一個(gè)數(shù),棧頂?shù)刂窚p1,即堆棧區(qū)是由內(nèi)存的低地址向高地址。另一種是每入棧一個(gè)數(shù),棧頂?shù)刂窚p1,每出棧一個(gè)數(shù),棧頂?shù)刂芳?,即堆棧區(qū)是由內(nèi)存的高地址向低地址。高地址、低地址是相對而言,即相對地址編碼的大小而言。

===============================================================

參考地址:

http://blog.csdn.net/fatshaw/article/details/5690073

http://hi.baidu.com/%C2%ED%D0%C2%CC%CE/blog/item/b3d8267b89d8cae62f73b35d.html

?

總結(jié)

以上是生活随笔為你收集整理的socket 大端 小端 转换 (转)《二》的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 免费在线观看黄网站 | 久久精品97 | 天堂成人av| www.黄色.| 婷婷国产 | 久久1024| 精品久久久久一区二区 | 国产91在线高潮白浆在线观看 | 色涩色 | 女人囗交吞精囗述 | 国产亚洲精品美女 | 瑟瑟网站在线观看 | 亚洲爱爱网站 | 亚洲AV无码乱码国产精品牛牛 | 巨骚综合 | 欧美日韩国产一区二区 | 老司机午夜免费视频 | 亚洲福利网 | 欧美一区高清 | 大尺度床戏揉捏胸视频 | 色小说香蕉 | 桃花久久 | 国模一区二区 | 中文字幕在线观看91 | 日韩成人欧美 | 日韩性生活视频 | 久久精品视频18 | 婷婷久久久久久 | 婷婷一区二区三区四区 | 国产乱子轮xxx农村 岛国久久久 | 国产三级精品在线观看 | 第一页国产 | 极品久久| 曰韩av| 国产精品国产三级国产专播品爱网 | 亚洲资源在线观看 | 关之琳三级全黄做爰在线观看 | 久在线| 亚洲成熟少妇视频在线观看 | 嫩草视频国产 | a级片免费网站 | 带aaa级的网名 | 国产拍拍拍拍拍拍拍拍拍拍拍拍拍 | 午夜精品久久久久久久四虎美女版 | 一区高清| 欧美成人日韩 | 国产精品97 | 澳门一级黄色片 | 久久国产精品久久久久久电车 | 狠狠躁日日躁 | 不卡免费视频 | 久久久久久久毛片 | 午夜在线看 | 欧美乱子伦 | 久久久久免费观看 | 在线观看亚洲精品视频 | 久草福利在线观看 | 在线观看视频日韩 | 一级的大片 | 久久99精品久久久久久噜噜 | 黄色三级小说 | 欧美伦理一区二区三区 | 在线观看亚洲视频 | aaa日韩 | 国产成人综合久久 | 免费人成视频在线播放 | 美日韩中文字幕 | 欧美日韩一区二区三区免费 | 国产91一区二区三区 | 国产91免费 | 久久精品美女 | 国产一级生活片 | 亚洲国产精品激情在线观看 | 天堂亚洲 | 亚洲国产经典 | 亚洲av无码国产精品永久一区 | 久久久久久久久久久网站 | 久久艹在线视频 | 日本人妻丰满熟妇久久久久久 | 国产成人超碰人人澡人人澡 | 国产精品一区二区无线 | 男人激烈吮乳吃奶爽文 | 欧洲亚洲自拍 | 超碰伊人久久 | 欧美做爰xxxⅹ性欧美大片 | 阿娇全套94张未删图久久 | 久色88| 蜜臀av性久久久久av蜜臀妖精 | 国产高清视频免费在线观看 | 性生活视频在线播放 | 日本在线网站 | 超碰免费公开在线 | 久久久久久久国产精品美女 | 欧美激情偷拍 | 又色又爽又黄gif动态图 | jlzzjlzz欧美大全 | 天天爽夜夜 | 日本女优黄色 | 在线一区二区视频 |