socket地址结构

通用socket地址

socket网络编程接口中表示socket地址的是结构体sockaddr,其定义如下:

1
2
3
4
5
#include <bits/socket.h>
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}

sa_family成员是地址族类型(sa_family_t)的变量。地址族类型通常与协议族类型是对应的。

image

sa_data成员用于存放socket地址值,不同的协议族的地址值具有不同的含义和长度:

image

专用socket地址

由于通用的socket地址在设置与获取IP和端口号时,需要执行烦锁的位操作,所以Linux为各个协议族提供了专门的socket地址结构体。

UNIX本地域协议

1
2
3
4
5
6
#include <sys/un.h>
struct sockaddr_un
{
sa_family_t sin_family; /* 地址族:AF_UNIX */
char sun_path[108]; /* 文件路径名 */
}

IPv4

1
2
3
4
5
6
7
8
9
10
11
12
#include <netinet/in.h>
struct sockaddr_in {
sa_family_t sin_family; /* 地址族:AF_INET */
u_in16_t sin_port; /* 端口号,要用网络字节序表示 */
struct in_addr sin_addr; /* IPv4地址结构体 */
char sin_zero[8]; /* 不使用字段,用于内存字节对齐 */
};

#include <arpa/inet.h>
struct in_addr{
in_addr_t s_addr; /* IPv4地址,要用网络字节序表示 */
};

IPv6

1
2
3
4
5
6
7
8
9
10
11
struct sockaddr_in6 {
sa_family_t sin_family; /* 地址族:AF_INET6 */
u_int16_t sin6_port; /* 端口号:要用网络字节序表示 */
u_int32_t sin6_flowinfo; /* 流信息:应设置为0 */
struct in6_addr sin6_addr; /* IPv6 地址结构体 */
u_int32_t sin6_scope_id; /* scope ID,尚处于实验阶段 */
};

struct in6_addr {
unsigned char sa_addr[16]; /* IPv6地址,要用网络字节序 */
};

所有专用socket地址类型在实际使用过程中,都必须转换为通过sock地址类型sockaddr,使用强制转换即可。因为所有的socket编程接口使用的socket地址参数的类型都是sockaddr。