Linux socket编程:地址及转换

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);

打印出来的信息如下,

  1. 结果是以16进制打印的,网络字节序是大端终结;对打印结果拆解一下就是,01 - 00 - 00 - ac;每个小数点隔开的数字都以一个字节存储,比如说AC就是172的16进制表示;
inet_pton: IP addr --> binary: 10000ac
  1. 恢复成字符串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

你可能感兴趣的:(Linux socket编程:地址及转换)