网络编程
网络编程
地址相关结构体
结构 | 场景 | 注意 |
---|---|---|
struct sockaddr { sa_family_t sa_family; // 地址族,如 AF_INET、AF_INET6 char sa_data[14]; // 地址数据 }; |
通用地址 | 不能直接用于bind,需要转为具体ipv4/6 |
struct sockaddr_in { sa_family_t sin_family; // AF_INET in_port_t sin_port; // 端口号(16 位),需要转换 struct in_addr sin_addr; // IPv4 地址(32位),需转换 }; |
ipv4地址 | - 端口号和ip必须经过转换才能设置。htons和inet_pton - 只能用于IPV4 |
struct sockaddr_in6 { sa_family_t sin6_family; // AF_INET6 in_port_t sin6_port; // 端口号(16 位),需要转换 struct in6_addr sin6_addr; // IPv6 地址 }; |
ipv6地址 | |
struct addrinfo { int ai_flags; // 选项,如 AI_PASSIVE(用于 bind() )int ai_family; // 地址族(AF_INET / AF_INET6 / AF_UNSPEC) int ai_socktype; // 套接字类型(SOCK_STREAM / SOCK_DGRAM) int ai_protocol; // 协议(通常为 0) size_t ai_addrlen; // 地址结构体大小 struct sockaddr *ai_addr; // 指向 sockaddr 结构体char *ai_canonname; // 规范主机名(可选) struct addrinfo *ai_next; // 指向下一个 addrinfo }; |
解析域名返回地址表,包含IPV4,IPV6。通常,用这些地址建立socket连接。 | - 与sockaddr不同,可以直接进行兼容编程。 - 用于getaddrinfo()解析主机,获取ip |
struct sockaddr_storage | 给足够大的空间,IPV4/6都可以通过这个存储。通常,用这个存储accept等得到的地址 |
套接字函数
函数 | 含义 | 注意 |
---|---|---|
int socket(int domain, int type, int protocol); | ||
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); | ||
int listen(int sockfd, int backlog); | ||
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); | ||
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); | ||
ssize_t send(int sockfd, const void *buf, size_t len, int flags); | ||
ssize_t recv(int sockfd, void *buf, size_t len, int flags); | ||
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); |
UDP 发送数据 | |
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); |
UDP 接收数据 | |
close(sockfd); |
其他辅助函数
函数 | 含义 | 注意 |
---|---|---|
inet_pton(AF_INET, “127.0.0.1”, &addr.sin_addr); | IP 地址转换:字符串 -> 二进制 | |
inet_ntop(AF_INET, &addr.sin_addr, ip_str, sizeof(ip_str)); | IP 地址转换:二进制 -> 字符串 | |
uint32_t htonl(uint32_t hostlong); | 字节序转换: 主机 -> 网络字节序(32 位) | |
uint16_t htons(uint16_t hostshort); | 字节序转换:主机 -> 网络字节序(16 位) | |
uint32_t ntohl(uint32_t netlong); | 字节序转换:网络 -> 主机字节序(32 位) | |
uint16_t ntohs(uint16_t netshort); | 字节序转换:网络 -> 主机字节序(16 位) |
未归:
-
getaddrinfo():实现具体依赖于网络库,所以在netdb.h中只是extern,并没有具体实现,真正的实现在glibc中,需要编译连接
-
SO_REUSEADDR 套接字选项:快速在同一端口重启。
TCP连接关闭,会进入TIME_WAIT状态,等待确保所有数据能够处理。 在这个状态下,端口不能重新绑定,直到连接上没有数据包流动。
默认情况下,TIME_WAIT会持续2-4分钟。取决于操作系统配置。
- TCP_NODELAY:Nagle算法会将小的数据包合成大的再发,等待缓冲区满了发。 启用不能保证实时性,
- TCP Keep-Alive :会在连接空闲时候发生保活包检测是否连接有效,如果指定时间内没有响应就断开
TCP_KEEPIDLE
:连接空闲多长时间后开始发送保活探测包(单位:秒)。TCP_KEEPINTVL
:保活探测包之间的时间间隔(单位:秒)。TCP_KEEPCNT
:在认为连接失效之前,最多发送多少个保活探测包。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 张彦东的博客!