Linux 设置 socket 状态
setsockopt 函数介绍
在 Linux 系统中,可以使用 setsockopt 函数设置 socket 状态。其函数原型如下:
int setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
参数说明:
参数 | 描述 |
---|---|
sockfd | 套接字描述符 |
level | 将被设置的选项的级别,如果想要在套接字级别上设置选项则使用 SOL_SOCKET |
optname | 指定准备设置的选项,optname 的选项取决于 level |
optval | 指向存放选项值的缓冲区 |
optlen | optval 缓冲区长度 |
返回值说明:执行成功返回 0,失败返回 -1,并设置 errno 的值。如下:
EBADF
:sockfd 不是有效的文件描述词EFAULT
:optval 指向的内存并非有效的进程空间EINVAL
:在调用 setsockopt() 时,optlen 无效ENOPROTOOPT
:指定的协议层不能识别选项ENOTSOCK
:sockfd 描述的不是套接字
级别(level)和选项(optname)参数如下:
#define SOL_SOCKET 1
#define SO_ACCEPTCONN 30
#define SO_BROADCAST 6
#define SO_DONTROUTE 5
#define SO_ERROR 4
#define SO_KEEPALIVE 9
#define SO_LINGER 13
#define SO_OOBINLINE 10
#define SO_RCVBUF 8
#define SO_RCVLOWAT 18
#define SO_RCVTIMEO 20
#define SO_REUSEADDR 2
#define SO_SNDBUF 7
#define SO_SNDLOWAT 19
#define SO_SNDTIMEO 21
#define SO_TYPE 3
#define SOL_IP 0
#define IP_DEFAULT_MULTICAST_TTL 1
#define IP_DEFAULT_MULTICAST_LOOP 1
#define IP_MAX_MEMBERSHIPS 20
SOL_SOCKET, SOL_IP, SOL_IPV6, SOL_TCP
级别 | 选项名称 | 说明 | 数据类型 |
---|---|---|---|
SOL_SOCKET | SO_BROADCAST | 允许发送广播数据 | int |
SO_DEBUG | 允许调试 | int | |
SO_DONTROUTE | 不查找路由 | int | |
SO_ERROR | 获得套接字错误 | int | |
SO_KEEPALIVE | 保持连接 | int | |
SO_LINGER | 延迟关闭连接 | struct linger | |
SO_OOBINLINE | 带外数据放入正常数据流 | int | |
SO_RCVBUF | 接收缓冲区大小 | int | |
SO_SNDBUF | 发送缓冲区大小 | int | |
SO_RCVLOWAT | 接收缓冲区下限 | int | |
SO_SNDLOWAT | 发送缓冲区下限 | int | |
SO_RCVTIMEO | 接收超时 | struct timeval | |
SO_SNDTIMEO | 发送超时 | struct timeval | |
SO_REUSERADDR | 允许重用本地地址和端口 | int | |
SO_TYPE | 获得套接字类型 | int | |
SO_BSDCOMPAT | 与 BSD 系统兼容 | int | |
IPPROTO_IP | IP_HDRINCL | 在数据包中包含 IP 首部 | int |
IP_OPTINOS | IP 首部选项 | int | |
IP_TOS | 服务类型 | int | |
IP_TTL | 生存时间 | int | |
IPPRO_TCP | TCP_MAXSEG | TCP 最大数据段的大小 | int |
TCP_NODELAY | 不使用 Nagle 算法 | int | |
设置选项
Keepalive 设置
- tcp_keepalive_time,在 TCP 保活打开的情况下,最后一次数据交换到 TCP 发送第一个保活探测包的间隔,即允许的持续空闲时长,或者说每次正常发送心跳的周期,默认值为 7200s(2h)。
- tcp_keepalive_probes 在 tcp_keepalive_time 之后,没有接收到对方确认,继续发送保活探测包次数,默认值为9(次)
- tcp_keepalive_intvl,在 tcp_keepalive_time 之后,没有接收到对方确认,继续发送保活探测包的发送频率,默认值为 75s。
发送频率 tcp_keepalive_intvl 乘以发送次数 tcp_keepalive_probes,就得到了从开始探测到放弃探测确定连接断开的时间
若设置,服务器在客户端连接空闲的时候,每90秒发送一次保活探测包到客户端,若没有及时收到客户端的 TCP Keepalive ACK 确认,将继续等待15秒*2=30秒。总之可以在90s+30s=120秒(两分钟)时间内可检测到连接失效与否。
以下改动,需要写入到 /etc/sysctl.conf 文件:
net.ipv4.tcp_keepalive_time=90
net.ipv4.tcp_keepalive_intvl=15
net.ipv4.tcp_keepalive_probes=2
端口重用
//1.closesocket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket:
bool opt=true;
setsockopt(socket,SOL_SOCKET ,SO_REUSEADDR,(const char*)&opt,sizeof(bool));
//2. 如果要已经处于连接状态的soket在调用closesocket后强制关闭,不经历TIME_WAIT的过程:
bool in= false;
setsockopt(socket,SOL_SOCKET,SO_DONTLINGER,(const char*)&in,sizeof(bool));