#if (('1234' >> 24) == '1')
printf("little\n");
#elif (('4321' >> 24) == '1')
printf("big\n");
#endif
Big Endian : PowerPC、IBM、Sun
Little Endian : x86、DEC
ARM的大小端是可選的。
常見的CPU、操作系統上使用的字節順序
CPU 操作系統 字節順序
x86 (Intel、AMD等) 所有 little-endian
DEC Alpha 所有 little-endian
HP-PA NT little-endian
HP-PA UNIX big-endian
SUN SPARC 所有 big-endian
MIPS NT little-endian
MIPS UNIX big-endian
PowerPC NT little-endian
PowerPC 非NT big-endian
RS/6000 UNIX big-endian
Motorola m68k 所有 big-endian
一般來說,我們不用關心字節順序問題,除非要涉及到跨平台的通信和資源共享
(網絡傳輸協議TCP/IP采用的是big- endian)。
假設現在要在使用不同字節順序的機器之間傳輸和交換數據,那該怎么辦呢?(同樣的數據,不同的機器可能有不同的理解,豈不是有悖初衷!)有兩種方法,一種是全部轉換成文本來傳輸,另一種是雙方都按照某一方的字節順序來傳輸(這時就有一個不同字節順序之間的相互轉換問題)。
Socket編程中經常采用第二種方法。整個傳輸過程如下:
發送端將本機的數據轉換成網絡的字節順序(調用API函數htonl或htons),然后發送;
接收端收到網絡數據后,先將數據轉換成本機的字節順序(調用API函數ntohl或ntohs),然后再進行其它操作——如此就能保證“會議精神”在通信雙方的正確傳達了!
cetty-core/src/cetty/buffer/ByteOrder.cpp
大小端問題主要涉及的是非單字節非字符串外的其余數據的表示和傳遞,如short型、int型等。
大小端的轉換只針對整數類型:short, int, long之類
對於char類型,二進制的字節流類型不存在大小端之間的轉換
http://www.cnblogs.com/my_life/articles/5351631.html
projects/authserver/ChatMsg.cpp
http://blog.csdn.net/u013281495/article/details/51166210
因為字節序往往和具體CPU架構有關,所以 如果你知道你的程序主要用戶群是什么平台,為了方便或者效率,你可以除了socket端口等需要在主機字節序和網絡字節序之間轉換外,其余數據的傳遞直接無視。例如 現在很多端游 都是如此。
因為現在大多數人使用的計算機都是X86體系結構的CPU+Windows操作系統,這部分用戶基本就是主流玩家,其他平台的玩家,除非獲得的回報率足夠多,否則沒必要花費太多時間關注。
先來說一下,常見的CPU架構的字節序吧:
Big Endian : PowerPC、IBM、Sun
Little Endian : x86、DEC
ARM的大小端是可選的。
最近隨着移動終端(大多為ARM處理器)和移動互聯網的爆發式發展,以后的游戲平台就不得不考慮一下大小端問題了。
大小端問題主要涉及的是非單字節非字符串外的其余數據的表示和傳遞,如short型、int型等。判斷主機大小端的方法有很多,常見的是聯合體判斷法,代碼如下:

01.bool isBigEndian() 
02.
{
03. union
04.
{
05. int a;
06. char b;
07. }num;
08. num.a = 0x1234;
09. return ( num.b == 0x12 )
14.}
出於效率考慮,我們有理由也完全應該 把大小端的處理放在客戶端,在客戶端socket過來時把服務器主機的大小端通知給客戶端,這樣服務器就不需要改動,直接傳遞數據就行,這時候可以在客戶端代碼中封裝幾個宏,在客戶端在收到數據后,根據那些宏來判斷是否轉換以及得出轉換后的數值。大小端轉換最有效也是最常見的方法就是移位法:
#define __SWP16(A) (( ((uint16)(A) & 0xff00) >> 8) | \
(( (uint16)(A) & 0x00ff) << 8)) 
#define __SWP32(A) ((( (uint32)(A) & 0xff000000) >> 24) | \
(( (uint32)(A) & 0x00ff0000) >> 8) | \
(( (uint32)(A) & 0x0000ff00) << 8) | \
(( (uint32)(A) & 0x000000ff) << 24))
聊了那么多,可能很多人要問 為什么 主機的字節序不統一呢? 這是因為 各個CPU廠商出於不同的邏輯考量,換句話說 大端和小端有其各自的優勢。
我們知道計算機正常的內存增長方式是從低到高(當然棧不是),取數據方式是從基址根據偏移找到他們的位置,從他們的存儲方式可以看出,大端存儲因為第一個字節就是高位,從而很容易知道它是正數還是負數,對於一些數值判斷會很迅速。
而小端存儲 第一個字節是它的低位,符號位在最后一個字節,這樣在做數值四則運算時從低位每次取出相應字節運算,最后直到高位,並且最終把符號位刷新,這樣的運算方式會更高效,也更符合我們手算的方式。當然這些都是自己的理解,如有不對,還望指正。
以下內容為自己總結:(協議部分都是大端,應用可以自己定 )
1、編程時,ip和port需要轉換成網絡字節序,這是網絡協議的規定,注意,ip和port並不是到達應用層數據的一部分,而是網絡層和傳輸層頭部的一部分,是屬於協議的一部分協議;
2、我們發送的數據是真正從發送端的應用層傳輸到接收端的應用層的數據,如果發送端和接收端字節序不一樣,那么就要考慮字節轉換。其根本是:網絡傳輸不一定要統一大端,小端也可以,只要保證2端一致就行了。因為服務器負擔大,這些工作就由客戶端去做,可以有以下兩種方式:1)編程之前,用文檔約束好,服務器采用的是大端或者小端,然后客戶端根據自己的大小端情況去轉換成與服務器一樣的字節序再發送和接受;2)客戶端連接服務器后,服務器先發送一個表示大小端的1字節的數據到客戶端,客戶端接收后得知服務器的大小端,以后發送和接收數據時作大小端的調整再發送和接收。
=============================================
http://blog.chinaunix.net/uid-15014334-id-4062785.html
建立好socket連接之后,
在小端模式下,發送數據0x12345678
通過wireshark抓包發現得到的數據為78562312,在接收端按字符接收並按字符打印為78563412
在大端模式下,發送數據0x12345678
通過wireshark抓包發現得到的數據為12345678,在接收端按字符接收並按字符打印為12345678
wireshark都是從地地址處開始發送數據的
=======================
http://bbs.bccn.net/m.thread.php?tid=396454
大端:低地址是高位數據
小端:低地址是低位數據
無論發送還是接收都是從低位開始的
先發的數據先被收到(有序的)
例子1大小端傳輸:
如小端機器發送short的0x0806,即高地址存放0x08,低地址存放0x06----------發送的時候從低地址開始讀取,即發送出去是0x0806(先發06,再發08;先收06,再收08)--------大端主機依次讀取從低地址開始存放數據,就是低地址存放0x06,高地址存放0x08,但是這個大端字節序,主機會把它解釋為0x0608.
例子2大端到大端傳輸:
如大端端機器發送short的0x0806,即高地址存放0x06,低地址存放0x08----------發送的時候從低地址開始讀取,即發送出去是0x0608(先發08,再發06;先收08,再收06)--------大端主機依次讀取從低地址開始存放數據,就是低地址存放0x08,高地址存放0x06,主機會把它解釋為0x0806.結果正確
例子3小端到小端傳輸:
如小端機器發送short的0x0806,即高地址存放0x08,低地址存放0x06----------發送的時候從低地址開始讀取,即發送出去是0x0806(先發06,再發08;先收06,再收08)--------小端主機依次讀取從低地址開始存放數據,就是低地址存放0x06,高地址存放0x08,主機會把它解釋為0x0806.結果正確
