内容简介:TCP连接一旦建立后,是不是这个连接可以一直保持? 答案是否定的,操作系统在实现TCP协议的时候都做了一个限制,这个限制可以参考配置:在Linux中我们可以通过修改 /etc/sysctl.conf 的全局配置:添加上面的配置后输入 sysctl -p 使其生效,你可以使用 sysctl -a | grep keepalive 命令来查看当前的默认配置
长连接与短连接
- 使用TCP协议时,会在客户端和服务器之间建立一条虚拟的信道,这条虚拟信道就是指连接,而建议这条连接需要3次握手,拆毁这条连接需要4次挥手,可见,我们建立这条连接是有成本的,这个成本就是效率成本,简单点说就是时间成本,你要想发送一段数据,必须先3次握手(来往3个包),然后才能发送数据,发送完了,你需要4次挥手(来往4个包)来断开这个连接。
- 其二,CPU资源成本,三次握手和4次挥手和发送数据都是从网卡里发送出去和接收的,还有其余的设备,比如防火墙,路由器等等,站在操作系统内核的角度来讲,如果我们是一个高并发系统的话,如果大量的数据包都经历过这么一个过程,那是很耗CPU的。
- 其三,每个socket是需要耗费系统缓存的,比如系统提供了一些接口设置socket缓存的,比如:
/proc/sys/net/ipv4/tcp_rmem /proc/sys/net/ipv4/tcp_wmem /proc/sys/net/ipv4/tcp_mem
keepalive机制
TCP连接一旦建立后,是不是这个连接可以一直保持? 答案是否定的,操作系统在实现TCP协议的时候都做了一个限制,这个限制可以参考配置:
cat /proc/sys/net/ipv4/tcp_keepalive_time cat /proc/sys/net/ipv4/tcp_keepalive_intvl cat /proc/sys/net/ipv4/tcp_keepalive_probes
- 我们看到默认这个tcp_keepalive_time的值为7200s,也就是2个小时,这个值代表如果TCP连接发送完最后一个ACK包后,如果超过2个小时,没有数据往来,那么这个连接会断掉。那么我们如何才能保持住这个连接呢?实际上,这就是TCP的keepalive机制,哦,说法不严谨,TCP协议并没有规定如此,但是很多的操作系统内核实现TCP协议时,都加上了这个keepalive机制,那么这个功能默认是关闭的,那这个keepalive机制到底是如何的呢?也就是,如果TCP之间没有任何数据来往了在tcp_keepalive_time(7200s,2h)后,服务器给客户端发送一个探测包,如果对方有回应,说明这个连接还存活,否则继续每隔tcp_keepalive_intvl(默认为75s)给对方发送探测包,如果连续tcp_keepalive_probes(默认为9)次后,依然没有收到对端的回复,那么则认为这个连接已经关闭。
- tcp keepalive默认不是开启的,如果想使用KeepAlive,需要在你的应用中设置SO_KEEPALIVE才可以生效。当然事先我们可以修改这些默认值,方法如下:
在 Linux 中我们可以通过修改 /etc/sysctl.conf 的全局配置:
net.ipv4.tcp_keepalive_time=7200 net.ipv4.tcp_keepalive_intvl=75 net.ipv4.tcp_keepalive_probes=9
添加上面的配置后输入 sysctl -p 使其生效,你可以使用 sysctl -a | grep keepalive 命令来查看当前的默认配置
tcp keepalive可以通过设置TCP选项设置,设置方法如下:
#include <sys/socket.h> int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len);
我们在需要使能Keepalive的socket上面调用setsockopt函数便可以打开该socket上面的keepalive。
第一个参数是要设置的套接字 第二个参数是SOL_SOCKET 第三个参数必须是SO_KEEPALIVE 第四个参数必须是一个布尔整型值,0表示关闭,1表示打开 最后一个参数是第四个参数值的大小。
示例:
int keepalive = 1; setsockopt(incomingsock,SOL_SOCKET,SO_KEEPALIVE,(void*)(&keepalive),(socklen_t)sizeof(keepalive)); int keepalive_time = 30; setsockopt(incomingsock, IPPROTO_TCP, TCP_KEEPIDLE,(void*)(&keepalive_time),(socklen_t)sizeof(keepalive_time)); int keepalive_intvl = 3; setsockopt(incomingsock, IPPROTO_TCP, TCP_KEEPINTVL,(void*)(&keepalive_intvl),(socklen_t)sizeof(keepalive_intvl)); int keepalive_probes= 3; setsockopt(incomingsock, IPPROTO_TCP, TCP_KEEPCNT,(void*)(&keepalive_probes),(socklen_t)sizeof(keepalive_probes));
设置SO_KEEPALIVE选项来开启KEEPALIVE,然后通过TCP_KEEPIDLE、TCP_KEEPINTVL和TCP_KEEPCNT设置keepalive的保活时间、间隔、次数等参数。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 没有 HTTP 连接池,空谈什么持久连接
- Linux中软连接和硬连接的区别
- sql – 哪个更好..左外连接还是右外连接?
- 连接池中的连接失效的几种处理方案
- 解决golang使用elastic连接elasticsearch时自动转换连接地址
- RedisPlus v2.0.0 发布,新增集群连接管理,支持 SSH 通道连接
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。