在Linux和Windows網絡編程時需要用到htons和htonl函數,用來將主機字節順序轉換為網絡字節順序。
在Intel機器下,執行以下程序




得到的結果是4096,初一看感覺很怪。
解釋如下,數字16的16進制表示為0x0010,數字4096的16進制表示為0x1000。 由於Intel機器是小尾端,存儲數字16時實際順序為1000,存儲4096時實際順序為0010。因此在發送網絡包時為了報文中數據為0010,需要經過htons進行字節轉換。如果用IBM等大尾端機器,則沒有這種字節順序轉換,但為了程序的可移植性,也最好用這個函數。
另外用注意,數字所占位數小於或等於一個字節(8 bits)時,不要用htons轉換。這是因為對於主機來說,大小尾端的最小單位為字節(byte)。
什么是大端模式(big-endian),為什么使用大端模式(big-endian)。
uint16_t htons(uint16_t hostshort);
htons的功能:將一個無符號短整型數值轉換為網絡字節序,即大端模式(big-endian)
參數u_short hostshort: 16位無符號整數
返回值:TCP / IP網絡字節順序
htons 是把你機器上的整數轉換成“網絡字節序”, 網絡字節序是 big-endian,也就是整數的高位字節存放在內存的低地址處。 而我們常用的 x86 CPU (intel, AMD) 電腦是 little-endian,也就是整數的低位字節放在內存的低字節處。舉個例子吧。假定你的port是0x1234,在網絡字節序里 這個port放到內存中就應該顯示成addr addr+1,也就是:0x12 0x34;而在x86電腦上,0x1234放到內存中實際是:addr addr+1,也就是:0x34 0x12。htons 的用處就是把實際內存中的整數存放方式調整成“網絡字節序”的方式。
第一個問題:為什么使用兩個字節,也就是16位來存儲。
這個簡單一些,因為一個字節只能存儲8位2進制數,而計算機的端口數量是65536個,也就是2^16,兩個字節。
第二個為題:為什么計算機需要大端模式和小端模式?
小端模式 :強制轉換數據不需要調整字節內容,1、2、4字節的存儲方式一樣。
大端模式 :符號位的判定固定為第一個字節,容易判斷正負。


|
大小尾端數據間的相互轉換
/*
usage: to convert between the form of big-endian and little-endian
author: ydzhang
date: 2008年12月6日20:23:48
*/
#include <stdio.h>
typedef unsigned int u32;
typedef unsigned short u16;
#define BSWAP_16(x) \
(u16) ( ((((u16)(x) & 0x00ff)) << 8) \
| (((u16)(x) & 0xff00) >> 8) )
u16 bswap_16(u16 x)
{
return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
}
u32 bswap_32(u32 x)
{
return ((x & 0x000000ff) << 24) |
((x & 0x0000ff00) << 8) |
((x & 0x00ff0000) >> 8) |
((x & 0xff000000) >> 24);
}
int main()
{
u16 num_16 = 0x1234;
u32 num_32 = 0x12345678;
printf("%x\n", bswap_16(num_16));
printf("%x\n", BSWAP_16(num_16));
printf("%x\n", bswap_32(num_32));
return 0;
}