网络字节序和地址转换

1:大小端字节序

参考博文:大小端模式

2:存储字节序和传输字节序

存储字节序:一个多字节的变量在内存中的存储方式,变量的小端数据存储在内存起始位置是小端字节序;变量的大端数据存储在内存起始位置是大端字节序;

传输字节序:协议传输多字节变量时的传输方式,先传输大端字节的方式成为大端字节序;先传输小端字节的方式成为小端字节;网络协议使用大端字节序传输数据,USB协议使用小端字节序传输协议;

两者关系:由于系统主机存在大小端模式,并且不能保证网络通信的两个主机之间的存储字节序一致,所以网络协议就规定自身在传输数据的时候使用的字节序为大端字节序,这样网络通信的双方主机就会达成一致,对接收到的数据(大端模式)依据自身的存储字节序来进行处理;存储字节序和传输字节序本质上是一样的概念;

3:字节序转换函数

#include 

uint16_t htons(uint16_t host16bitvalue)   //返回网络字节序的值
uint32_t htonl(uint32_t host32bitvalue)   //返回网络字节序的值

uint16_t ntohs(uint16_t net16bitvalue)    //返回主机字节序的值
uint32_t ntohl(uint32_t net32bitvalue)    //返回主机字节序的值
上述函数中,h代表host,n代表network,s代表short,l代表short;

当使用这些函数时,我们并不关心主机字节序和网络字节序的真实值,只要调用适当的函数在主机和网络字节序之间转换某个给定的值,因为在那些与网络字节序(大端字节序)相同的系统中,这些函数为空,如下代码:

#ifdef __OPTIMIZE__
/* We can optimize calls to the conversion functions.  Either nothing has
    to be done or we are using directly the byte-swapping functions which
    often can be inlined.  */
 # if __BYTE_ORDER == __BIG_ENDIAN
 /* The host byte order is the same as network byte order,
    so these functions are all just identity.  */
 # define ntohl(x)   (x)
 # define ntohs(x)   (x)
 # define htonl(x)   (x)
 # define htons(x)   (x)
 # else
 #  if __BYTE_ORDER == __LITTLE_ENDIAN
 #   define ntohl(x) __bswap_32 (x)
 #   define ntohs(x) __bswap_16 (x)
 #   define htonl(x) __bswap_32 (x)
 #   define htons(x) __bswap_16 (x)
 #  endif
 # endif 
 #endif  

如果主机系统的字节序为大端模式,这些函数定义为空,在进行socket编程的时候,为了提高代码的可移植性,应该总是使用这些函数进行主机字节序和网络字节序的处理;

函数使用举例:

#include 
#include 

int main(int argc,char **argv)
{
	int value1 = 0x12345678;          //定义一个4字节的数据
	short int value2 = 0x1234;        //定义一个2字节的数据
	printf("htonl(0x%08x) = 0x%08x\r\n",value1,htonl(value1));
	printf("htons(0x%04x) = 0x%04x\r\n",value2,htons(value2));
}
代码执行如下:

网络字节序和地址转换_第1张图片

4:地址转换函数

使用协议无关性的两个地址处理函数,函数如下:

#include 

//返回:若成功返回1,若输入不是有效的表达格式返回0,出错返回-1
int inet_pton(int family,const char *strptr, void *addrptr);

//返回:若成功则为指向结果的指针,若出错则为NULL
const char *inet_ntop(int family,const void *addrptr,char *strptr,size_t len);
函数使用举例:

#include 
#include 

int main(int argc,char **argv)
{
	unsigned char address[4];   //存放ip地址
	char str[INET_ADDRSTRLEN] = {0};
	char *string = NULL;
	
	string = "192.168.1.1";
	inet_pton(AF_INET,string,address);
	printf("%d %d %d %d\r\n",address[0],address[1],address[2],address[3]);

	address[0] = 127;address[1] = 127;address[2] = 33;address[3] = 33;
	inet_ntop(AF_INET,address,str,16);
	printf("%s\r\n",str);

	return 0;
}

代码执行如下:

网络字节序和地址转换_第2张图片

由代码验证可知,inet_pton函数转换完成后存放在address数组中的字节序已经是网络字节序(大端字节序);







你可能感兴趣的:(socket)