sockaddr

通用地址结构。

1
2
3
4
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
};

通常不直接使用,而是作为函数参数类型。

例如:

1
bind(sockfd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));

sockaddr_in

IPv4 地址结构。

1
2
3
4
5
6
7
#include <netinet/in.h>

struct sockaddr_in {
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
};

常用示例:

1
2
3
4
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = INADDR_ANY;

in_addr

IPv4 地址结构。

1
2
3
struct in_addr {
in_addr_t s_addr;
};

设置 IP:

1
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);

sockaddr_in6

IPv6 地址结构。

1
2
3
4
5
6
7
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;
};

示例:

1
2
3
4
sockaddr_in6 addr6{};
addr6.sin6_family = AF_INET6;
addr6.sin6_port = htons(8080);
inet_pton(AF_INET6, "::1", &addr6.sin6_addr);

sockaddr_storage

通用地址存储结构,可以容纳 IPv4 或 IPv6。

1
2
3
struct sockaddr_storage {
sa_family_t ss_family;
};

常用于同时支持 IPv4 和 IPv6 的程序。

字节序转换函数

网络传输使用大端字节序,即网络字节序。

常用函数:

函数 说明
htons host to network short,16 位
htonl host to network long,32 位
ntohs network to host short
ntohl network to host long

示例:

1
2
3
uint16_t port = 8080;
uint16_t netPort = htons(port);
uint16_t hostPort = ntohs(netPort);

IP 地址转换函数

inet_pton

字符串 IP 转二进制。

1
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);

inet_ntop

二进制 IP 转字符串。

1
2
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &addr.sin_addr, ip, sizeof(ip));

示例:

1
2
3
4
5
6
7
8
sockaddr_in client{};
char ip[INET_ADDRSTRLEN];

inet_ntop(AF_INET, &client.sin_addr, ip, sizeof(ip));

std::cout << "client ip: " << ip
<< ", port: " << ntohs(client.sin_port)
<< std::endl;