文章目录
  1. 通用socket地址
  2. 专用socket地址
  3. IP地址转换

通用socket地址

表示socket地址的结构体sockaddr。

1
2
3
4
5
6
7
8
9
/*
引用方式: #include <sys/socket.h>
sa_family: 地址族类型变量. AF_UNIX/PF_UNIX表示UNIX本地域协议族 || AF_INET/PF_INET表示TCP/IPv4协议族 || AF_INET6/PF_INET6表示TCP/IPv6协议族
sa_data: 存放socket地址值. sa_data表示路径名(AF_UNIX类型) || sa_data包含2字节的端口号与4字节IPv4地址(AF_INET类型) || sa_data包含2字节端口号, 4字节流标识, 16字节IPv6地址, 4字节范围ID共26字节(AF_INTE6类型)
*/
struct sockaddr{
sa_family_t sa_family;
char sa_data[14];
};

14字节的sa_data无法容纳所有协议族的地址值;因此,Linux定义了如下新的通用socket地址结构体sockaddr_storage。

1
2
3
4
5
6
7
8
/*
引用方式: #include <sys/socket.h>
*/
struct sockaddr_storage{
sa_family_t ss_family;
char __ss_padding[(128 - (sizeof (unsigned short int)) - sizeof (unsigned long int))];
unsigned long int __ss_align;
};

专用socket地址

上述通用socket结构体不易操作,Linux专门提供如下专用socket地址结构体。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/*
引用方式: #include <sys/un.h>
UNIX本地域协议族
*/
struct sockaddr_un{
sa_family_t sun_family;
char sun_path[108];
};
/*
引用方式: #include <netinet/in.h>
TCP/IPv4协议族
sin_port: 使用网络字节序
*/
struct sockaddr_in{
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[sizeof (struct sockaddr) -
(sizeof (unsigned short int)) -
sizeof (in_port_t) -
sizeof (struct in_addr)];
};

struct in_addr{
in_addr_t s_addr;// IPv4地址; 使用网络字节序
};
/*
引用方式: #include <netinet/in.h>
TCP/IPv6协议族
sin_port6: 使用网络字节序
*/
struct sockaddr_in6{
sa_family_t sin6_family;
in_port_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr;
uint32_t sin6_scope_id;
};

struct in6_addr{
union{
uint8_t __u6_addr8[16];
uint16_t __u6_addr16[8];
uint32_t __u6_addr32[4];
} __in6_u;// IPv6地址; 使用网络字节序
};

所有专用socket地址类型的变量在实际使用时都需要转化为通用socket地址类型sockaddr。

IP地址转换

点分十进制字符串转结构体in_addr。

1
2
3
4
5
6
/*
引用方式: #include <arpa/inet.h>
inp: 转换的结构体存放地址
返回1: 成功 || 返回0: 失败
*/
int inet_aton(const char * cp, struct in_addr * inp);

结构体in_addr转点分十进制字符串。

1
2
3
4
/*
引用方式: #include <arpa/inet.h>
*/
char * inet_ntoa(struct in_addr in);

上述两个函数不可重入

还有同时适用于IPv4与IPv6地址转换的一对函数。

点分十进制字符串(IPv4地址)或冒号分16进制字符串(IPv6)转对应结构体,即结构体in_addr或结构体in6_addr;由__af参数指定协议族,一般取宏AF_INET或AF_INET6。

1
2
3
4
5
6
/*
引用方式: #include <arpa/inet.h>
af: 指定地址族; AF_INET: IPv4 || AF_INET6: IPv6
buf: 转换的结构体存放地址
*/
int inet_pton (int __af, const char * cp, void * buf);

结构体in_addr或结构体in6_addr转换为对应的字符串表示。

1
2
3
4
5
6
7
8
/*
引用方式: #include <arpa/inet.h>
af: 指定地址族; AF_INET: IPv4 || AF_INET6: IPv6
buf: 字符串存储地址
len一般取两个宏INET_ADDRSTRLEN与INET6_ADDRSTRLEN;
返回目标存储地址: 成功 || 返回NULL并设置erno: 失败
*/
const char * inet_ntop (int af, const void * cp, char * buf, socklen_t len);