1. 网络字节序与主机字节序
1.1 主机字节序()
CPU的字节顺序类型,
- 小端,little endian;
- 大端,big endian;
1.2 网络字节序
TCP/IP中规定好的一种数据表示格式,它与具体使用的CPU类型和操作系统类型无关;网络字节序固定的采用大端终结的方式
1.3 字节序转换函数
- htons:主机序 -> 网络序,处理unsigned short类型;
- htonl:主机序 -> 网络序,处理unsigned long类型;
- ntohs:网络序 -> 主机序, 处理unsigned short类型;
- ntohl:网络序 -> 主机序,处理unsigned long类型;
2. Socket地址结构
2.1 sockaddr结构体
定义如下,这个结构体会作为bind、connect、recvfrom、sendto等函数的输入地址参数结构体,
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
这里的sa_data包含了地址+端口号
2.2 sockaddr_in结构体
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
这个结构体的大小和sockaddr结构体的大小一致,可以互相转换;
在网络编程中我们会对sockaddr_in的结构体进行操作赋值,使用这个结构体建立地址信息;然后强制类型转换成sockaddr并传递给调用函数,
struct sockaddr_in servaddr;
bzero( (void *)&servaddr, sizeof(servaddr) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
servaddr.sin_port = htons(MY_PORT_NUM);
sctp_bindx( sock_fd, (struct sockaddr *)&servaddr, addr_count, SCTP_BINDX_ADD_ADDR)
- 使用htonl和htons进行字节序转换;
- 强制类型转换sockaddr_in到sockaddr作为bind的输入参数;
3. 转换函数
3.1 inet_ntop函数
函数把一个网络字节序的二进制的IP地址转换成一个ASCII类型的IP,定义如下,
#include
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
- af 代表地址族,比如说AF_NET或者AF_INET6;
- 这个函数把src地址转换结果保存到dst指向的buffer中;比如说IPv4的时候把一个in_addr的结构体转换成“ddd. ddd. ddd. ddd”的IP地址结构;
3.2 inet_pton函数
这个函数的功能和inet_ntop函数恰好相反,
#include
int inet_pton(int af, const char *src, void *dst);
转换的网络序的二进制IP会写入dst指向的内存中;这个函数可以用来把一个IP字符串转换并赋值给地址结构体;
来看一个简单的例子,
struct sockaddr_in sa;
char ip[20];
inet_pton(AF_INET, "172.0.0.1", &(sa.sin_addr));
printf("[inet_pton]: IP addr --> binary: %x\n", sa.sin_addr);
inet_ntop(AF_INET, &(sa.sin_addr), ip, 20);
printf("[inet_ntop]: binary --> IP address: %s\n", ip);
打印出来的信息如下,
- 结果是以16进制打印的,网络字节序是大端终结;对打印结果拆解一下就是,01 - 00 - 00 - ac;每个小数点隔开的数字都以一个字节存储,比如说AC就是172的16进制表示;
inet_pton: IP addr --> binary: 10000ac
- 恢复成字符串IP地址
[inet_ntop]: binary --> IP address: 172.0.0.1
3.3 inet_addr函数
把一个小数点分隔的IP转换成一个网络字节序的长整型的数(u_long)
in_addr_t inet_addr(const char *cp);
举个简单的例子
printf("[inet_addr]: IP addr --> binary: %x\n", inet_addr("172.0.0.1"))
打印结果
[inet_addr]: IP addr --> binary: 10000ac