TCPIP 网络编程-03-地址族与数据序列

上一章《套接字类型与协议设置》是构建套接字,这一章就是给地址分配 IP 地址和端口号

首先是结构体

1
2
3
4
5
6
7
8
9
10
11
12
struct sockaddr_in
{
sa_family_t sin_family; //地址族(Address Family) __uint8_t
uint16_t sin_port; //16 位 TCP/UDP 端口号
struct in_addr sin_addr; //32 位 IP 地址
char sin_zero[8]; //不使用
}

struct in_addr
{
in_addr_t s_addr; //32 位 IPv4 地址 (__uint32_t)
}

其中 sin_zero 是为了 使 struct sockaddr_instruct sockaddr 结构大小一致而插入的成员,必须填充为0

struct sockaddr 的结构如下

1
2
3
4
5
struct sockaddr
{
sa_family_t sin_family; //协议族
char sa_data[14]; //地址信息
}

sa_data 保存的地址信息包含了地址与端口号,剩余部分填充为0

tips: 服务端套接字虽然要绑定一个端口,但是同一个端口 TCP套接字和UDP套接字是可以共用的(虽然一般不共用)

字节序转换有以下内容

  1. 网络字节序规定统一使用大端
  2. 如何记住大小端:端(即 开端),地址从低到高,低字节在低地址就是小端,高字节在低地址就是大端
  3. 即使系统本身是大端,最好也调用一下,反正也不会有任何变化。提升代码兼容性

字节序转换函数

1
2
3
4
unsigned short htons(unsigned short);
unsigned short ntohs(unsigned short);
unsigned long ntohl(unsigned long);
unsigned long ntohl(unsigned long);

网络地址的转换

1
2
3
4
5
6
7
8
#include <arpa/inet.h>
//成功时返回32位大端序整数型值,失败返回INADDR_NONE(检查无效IP地址)
in_addr_t inet_addr(const char * string);

//与上面功能一样,成功返回1,失败返回0
int inet_aton(const char * string, struct in_addr *addr);
//将网络字节序地址转换为字符串形式(注意返回结果的释放)
char *inet_ntoa(struct in_addr *addr);

ntoa 可以理解为 network to addressaton 同理

重写代码地址:https://github.com/XBoom/network-ip.git 中的 apps/socket/05/执行结果

1
2
3
4
5
6
7
8
9
[05/server.c:16 main info] host ordered port: 0x1234 
[05/server.c:17 main info] net ordered addr: 0x3412
[05/server.c:18 main info] host ordered post: 0x12345678
[05/server.c:19 main info] net ordered post: 0x12345678
[05/server.c:31 main info] inet addr 127.0.0.1 success 0x100007f
[05/server.c:37 main error] inet addr 127.0.0.258 failed
[05/server.c:53 main info] inet_aton 127.0.0.1 success 0x100007f
[05/server.c:58 main error] inet_aton 127.0.0.258 failed
[05/server.c:69 main info] inet ntoa 127.0.0.1 127.0.0.1

参考文档

  1. 《TCPIP 网络编程》