Linux网络编程之确定主机字节序及网络字节序的转换

字节顺序,又称端序或尾序(英语:Endianness)。在计算机科学领域中,是跨越多字节的程序对象的存储规则。在几乎所有的机器上,多字节对象都被存储为连续的字节序列。例如在C语言中,一个类型为int的变量x地址为0x100,那么其对应地址表达式&x的值为0x100。且x的四个字节将被存储在存储器的0x100, 0x101, 0x102, 0x103位置。

而存储地址内的排列则有两个通用规则。一个多位的整数将按照其存储地址的最低或最高字节排列。如果最低有效位在最高有效位的前面,则称小端序;反之则称大端序。在网络应用中,字节序是一个必须被考虑的因素,因为不同机器类型可能采用不同标准的字节序,所以均按照网络标准转化。

例如假设上述变量x类型为int,位于地址0x100处,它的十六进制为0x12345678,地址范围为0x100~0x103字节,其内部排列顺序依赖于机器的类型。

字节序 0x100 0x101 0x102 0x103
小端 0x78 0x56 0x34 0x12
大端 0x12 0x34 0x56 0x78

网络传输一般采用大端序,也被称之为网络字节序,或网络序。IP协议中定义大端序为网络字节序。Berkeley套接字定义了一组转换函数,用于16和32bit整数在网络序和本机字节序之间的转换。htonl,htons用于本机序转换到网络序;ntohl,ntohs用于网络序转换到本机序。

一、 字节序转换函数

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

uint32_t ntohl(uint32_t netlong);

uint16_t ntohs(uint16_t netshort);

二、 示例代码

#include <stdio.h>
#include <arpa/inet.h>

union order
{
	unsigned int value;
	unsigned char data[sizeof(int)];
};

void print(union order d)
{
	for(int i=0; i<sizeof(int); i++)
	{
		printf("%p:\t0x%x\n", &d.data[i], d.data[i]);
	}
}

int main(void)
{
	union order d;
	d.value = 0x12345678;
	
	printf("Host byte order:\n");
	print(d);
	
	d.value = htonl(d.value);
	
	printf("network byte order:\n");
	print(d);
	
	return 0;
}

三、 运行结果

[root@localhost workspace]# gcc byte_order.c -o byte_order -std=gnu99 -Wall
[root@localhost workspace]# ./byte_order
Host byte order:
0x7fffa9ed8e20: 0x78
0x7fffa9ed8e21: 0x56
0x7fffa9ed8e22: 0x34
0x7fffa9ed8e23: 0x12
network byte order:
0x7fffa9ed8e20: 0x12
0x7fffa9ed8e21: 0x34
0x7fffa9ed8e22: 0x56
0x7fffa9ed8e23: 0x78

至此,我们可以确定主机字节序为小端,网络字节序为大端。

Leave a Reply

Your email address will not be published. Required fields are marked *