getsockopt、setsockopt
int getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlen);
- 获取套接字属性
socket
:输入参数,要操作的socket套接字level
:输入参数,协议层:SOL_SOCKET
通用套接字选项、IPPROTO_IP
IP选项、IPPROTO_TCP
TCP选项optname
:输入参数,访问的选项名optval
:输出参数,保存选项的值optlen
:输入参数,指明optval的长度- 返回值:成功返回0,失败返回-1,并设置errno
int setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen);
- 设置套接字属性
socket
:输入参数,要操作的socket套接字level
:输入参数,协议层,同getsockopt()optname
:输入参数,访问的选项名optval
:输入参数,要设置的值optlen
:输入参数,指明optval的长度- 返回值:成功返回0,失败返回-1,并设置errno
常用的socket选项:
SO_REUSEADDR
一般来说,一个端口释放后会等待两分钟之后才能再被使用,这段时间主要消耗在了TIME_WAIT
状态上;
正常情况下只有当socket的状态为CLOSED
的时候才能被重新利用,不过我们可以使用SO_REUSEADDR
选项来重用TIME_WAIT的端口
打开端口重用选项:
1
2
int on = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
TCP_NODELAY
TCP_NODELAY 选项的作用是:禁用默认开启的 Nagle 算法。
Nagle 算法
Nagle 算法是以他的发明人 John Nagle 的名字命名的,它用于自动连接许多的小缓冲器消息,通过减少必须发送包的个数来增加网络软件系统的效率。
简单来讲,就是将多段小数据合并为一个数据包,一次性发送,提高网络通信效率。
但是,这个算法对于现代网络来说已经不适用了,因为现在都是强调数据的实时性。
而默认情况下,该算法是启用的,因此,我们需要手动设置 TCP_NODELAY 来禁用它。
禁用 Nagle 算法:
1
2
int on = 1;
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
SO_KEEPALIVE
tcp保持长连接主要有两种方式:
第一种,使用应用层面的心跳机制,定期发送一个心跳包,检测对方是否还活着
第二种,使用tcp协议自带的keepalive机制,让tcp自己发送心跳包,这里推荐这种方式,更清爽彻底
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 打开tcp keepalive选项
int keepalive = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)) < 0){
perror("\033[1;35m[WARNING]\033[0m setsockopt_keepalive");
}
// 设置空闲时长(即多久不收发数据就开始触发心跳机制,发送心跳包)
int idle = 30;
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle)) < 0){
perror("\033[1;35m[WARNING]\033[0m setsockopt_keepidle");
}
// 设置心跳包发送时间间隔(即两个心跳包之间的发送时间间隔)
int interval = 60;
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval)) < 0){
perror("\033[1;35m[WARNING]\033[0m setsockopt_keepintvl");
}
// 设置允许探测失败的最大次数(即连续3次探测失败,说明对方已断开连接)
int cnt = 3;
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)) < 0){
perror("\033[1;35m[WARNING]\033[0m setsockopt_keepcnt");
}