字節序#
字節序:存放字節的順序。
字節序與 CPU 架構相關,通常 x86 架構使用小端序,字節序決定數據在內存中存儲的順序。
在網絡通信傳輸數據時需要統一字節序,以確保能夠正常的傳輸和解析數據。
存儲數據方式有:大端序(Big-Endian)和 小端序(Little-Endian)。
大端序:高位字節存儲在低地址,低位字節存儲在高地址(低對高)。
小端序:高位字節存儲在高地址,低位字節存儲在低地址(低對低)。
對於 0x1234
十六進制的數,12
是高位字節,34
是低位字節。而高地址和低地址指的是地址的大小,例如有兩個地址 0x1010
和 0x1011
,0x1010
就是低地址,0x1011
就是高地址。
判斷本機字節序#
// 1 Byte = 8 bit(8 位二進制代表一個字節)
// 1 位十六進制代表 4 bit
// short 占 2 Byte = 16 bit
// char 占 1 Byte = 8 bit
// 強轉為 char *,後取出的首地址(低位地址)占 1 Byte
// 將這個低位地址解引用後轉為 short
// 與原始數據中的低位和高位進行比較
// 如果等於高位則說明為大端序(低對高)
// 如果等於低位則說明為小端序(低對低)
// 如果是大端序,低地址存儲數據的高位字節
// 高位字節是 0x12
// &i 取出的是低地址
// (short)*(char *)&i == 0x12
bool isBigEndian() {
short i = 0x1234;
return (short)*(char *)&i == 0x12;
}
// 如果是小端序,低地址存儲數據的低位字節
// 低位字節是 0x34
// &i 取出的是低地址
// (short)*(char *)&i == 0x34
bool isLittleEndian() {
short i = 0x1234;
return (short)*(char *)&i == 0x34;
}
簡單寫法:
bool isBigEndian() {
short i = 1;
return *(char *)&i != 1;
}
轉換本機字節序與網絡字節序#
網絡字節序通常使用大端字節序。
POSIX API#
// host to network unsigned short
htons();
// host to network unsigned long
htonl();
// network to host unsigned short
ntohs();
// network to host unsigned long
ntohl();
Boost Asio API#
// host to network unsigned short
boost::asio::detail::socket_ops::host_to_network_short();
// host to network unsigned long
boost::asio::detail::socket_ops::host_to_network_long();
// network to host unsigned short
boost::asio::detail::socket_ops::network_to_host_short();
// network to host unsigned long
boost::asio::detail::socket_ops::network_to_host_long();
在使用這些 API 時,應該確保輸入參數和返回結果都是無符號整型,否則可能存在符號拓展問題。