转自:https://blog.csdn.net/chrisnotfound/article/details/80111559

1. TCP Keepalive的起源

TCP协议中有长连接和短连接之分。
短连接环境下,数据交互完毕后,主动释放连接;
长连接的环境下,进行一次数据交互后,很长一段时间内无数据交互时,客户端可能意外断电、死机、崩溃、重启,还是中间路由网络无故断开,这些TCP连接并未来得及正常释放,那么,连接的另一方并不知道对端的情况,它会一直维护这个连接,长时间的积累会导致非常多的半打开连接,造成端系统资源的消耗和浪费,且有可能导致在一个无效的数据链路层面发送业务数据,结果就是发送失败。所以服务器端要做到快速感知失败,减少无效链接操作,这就有了TCP的Keepalive(保活探测)机制。

2. TCP Keepalive工作原理

当一个 TCP 连接建立之后,启用 TCP Keepalive 的一端便会启动一个计时器,当这个计时器数值到达 0 之后(也就是经过tcp_keep-alive_time时间后),一个 TCP 探测包便会被发出。这个 TCP 探测包是一个纯 ACK 包(规范建议,不应该包含任何数据,但也可以包含1个无意义的字节,比如0x0。),其 Seq号 与上一个包是重复的,所以其实探测包报文不在窗口控制范围内。

如果一个给定的连接在两小时内(默认时长)没有任何的动作,则服务器就向客户发一个探测报文段,客户主机必须处于以下4个状态之一:

  1. 客户主机依然正常运行,并从服务器可达。客户的TCP响应正常,而服务器也知道对方是正常的,服务器在两小时后将保活定时器复位。

  2. 客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的TCP都没有响应。服务端将不能收到对探测的响应,并在75秒后超时。服务器总共发送10个这样的探测 ,每个间隔75秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止连接。

  3. 客户主机崩溃并已经重新启动。服务器将收到一个对其保活探测的响应,这个响应是一个复位,使得服务器终止这个连接。

  4. 客户机正常运行,但是服务器不可达,这种情况与2类似,TCP能发现的就是没有收到探测的响应。

对于linux内核来说,应用程序若想使用TCP Keepalive,需要设置SO_KEEPALIVE套接字选项才能生效。

三个重要的参数

  1. tcp_keepalive_time,在TCP保活打开的情况下,最后一次数据交换到TCP发送第一个保活探测包的间隔,即允许的持续空闲时长,或者说每次正常发送心跳的周期,默认值为7200s(2h)。

  2. tcp_keepalive_probes 在tcp_keepalive_time之后,没有接收到对方确认,继续发送保活探测包次数,默认值为9(次)

  3. tcp_keepalive_intvl,在tcp_keepalive_time之后,没有接收到对方确认,继续发送保活探测包的发送频率,默认值为75s。

其他编程语言有相应的设置方法,这里只谈linux内核参数的配置。例如C语言中的setsockopt()函数,java的Netty服务器框架中也提供了相关接口。

3. TCP Keepalive作用

① 探测连接的对方是否存活
在应用交互的过程中,可能存在以下几种情况:
(1)客户端或服务器意外断电,死机,崩溃,重启。
(2)中间网络已经中断,而客户端与服务器并不知道。
利用保活探测功能,可以探知这种对端的意外情况,从而保证在意外发生时,可以释放半打开的TCP连接。
② 防止中间设备因超时删除连接相关的连接表
中间设备如防火墙等,会为经过它的数据报文建立相关的连接信息表,并为其设置一个超时时间的定时器,如果超出预定时间,某连接无任何报文交互的话,
中间设备会将该连接信息从表中删除,在删除后,再有应用报文过来时,中间设备将丢弃该报文,从而导致应用出现异常。

4. 使用方法

结构体使用

struct tcp_keepalive {ULONG onoff ;//是否开启 keepaliveULONG keepalivetime ; //多长时间(ms)没有数据就开始心跳包ULONG keepaliveinterval ; // 每隔多长时间(ms)发送一个心跳包,
};

这个结构体设置了空闲检测时间,及检测时重复发送的间隔时间。此外, tcp_keepalive 这个结构体中没有对重试次数这个参数的设置,这个参数可以通过注册表来设置,具体位置为:
HKLM/SYSTEM/CurrentControlSet/Services/Tcpip/Parameters/TcpMaxDataRetransmissions

实际程序

 #include <mstcpip.h>BOOL bKeepAlive = TRUE;int nRet = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&bKeepAlive, sizeof(bKeepAlive));if (nRet == SOCKET_ERROR){TRACE(L"setsockopt failed: %d/n", WSAGetLastError());return FALSE;}//设置tcp_keepalive参数tcp_keepalive alive_in;tcp_keepalive alive_out;alive_in.keepalivetime    = 500;  // 0.5salive_in.keepaliveinterval  = 1000; //1salive_in.onoff= 1;unsigned long ulBytesReturn = 0;nRet = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &alive_in, sizeof(alive_in),&alive_out, sizeof(alive_out), &ulBytesReturn, NULL, NULL);if (nRet == SOCKET_ERROR){TRACE(L"WSAIoctl failed: %d/n", WSAGetLastError());return FALSE;}

其中, setsockopt 设置了 keepalive 模式,但是系统对 keepalive 默认的参数可能不符合我们的要求,所以利用WSAIoctl函数通过 tcp_keepalive 结构体对这些参数进行了相应设置

TCP长连接(KeepAlive)相关推荐

  1. TCP长连接保持连接状态TCP keepalive设置

    出处:http://blog.csdn.net/embedded_sky/article/details/42077321 对于TCP长连接保活是十分必要的,原因如下: 1.系统多在OA网和外网间有防 ...

  2. 应用服务器与数据库之间是长连接,要接收多个 tcp 长连接不断发送的数据并存储,哪些数据库或数据存储方案比较合适?...

    在服务器建立服务端,与多个 tcp 连接保持长连接,服务端会根据客户端发送的 token 验证确定是否保持长连接建立"session"缓存, 在某个状态开启时(我称为存储状态),要 ...

  3. c语言linux TCP长连接 socket收发范例 断开自动重连

    原文链接:https://blog.csdn.net/chenhao0568/article/details/103420615 c语言linux TCP长连接 socket收发范例 断开自动重连 改 ...

  4. tcp长连接和保活时间

    tcp长连接和保活时间 TCP协议中有长连接和短连接之分.短连接在数据包发送完成后就会自己断开,长连接在发包完毕后,会在一定的时间内保持连接,即我们通常所说的Keepalive(存活定时器)功能.   ...

  5. 网络:tcp长连接与短连接

    当网络通信采用tcp协议时,在真正的读写操作之前,sever与client之间必须建立一个连接,当读写操作完成之后,对方不再需要这个连接时他们可以释放这个链接,连接的连接需要三次握手,释放需要四次握手 ...

  6. TCP长连接和HTTP长连接对比

    TCP长连接和HTTP长连接 1. TCP长连接 TCP长连接是一种保持TCP连接的机制.当一个TCP连接建立之后,启用TCP Keep Alive的一端便会启动一个计时器,当这个计时器到达0之后,一 ...

  7. TCP长连接与短连接、心跳机制

    转自: 1. TCP连接 当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立是 ...

  8. 【TCP长连接】使用TCP长连接提升服务性能

    1.概述 在<性能优化篇-理论基础>中,我们知道了提升服务性能的两个思路,分别是提升服务并发能力和降低请求的响应时间(RT).一个请求的响应时间包括两部分,等待时间和执行时间.在<性 ...

  9. TCP长连接,心跳机制介绍

    TCP长连接,心跳机制介绍 长连接 为何要长连接 心跳 心跳为何设置在服务器端 心跳维持长连接 TCP keep-alive的三个参数 参数的具体意义 心跳的使用场景 长连接 TCP经过三次握手建立连 ...

  10. TCP握手机制、TCP长连接和短连接、TCP 保活机制 、心跳机制

    参考: https://www.cnblogs.com/Andya/p/7272462.html 1. TCP连接(3次握手建立连接.4次挥手关闭连接) 当网络通信时采用TCP协议时,在真正的读写操作 ...

最新文章

  1. LeetCode UTF-8 Validation
  2. 对象检测目标小用什么模型好_[目标检测] YOLO4论文中文版
  3. [云炬创业学笔记]第一章创业是什么测试16
  4. 经典C语言程序100例之七五
  5. Spring中ApplicationContextAware的用法
  6. 深度学习之 FPN (Feature Pyramid Networks)
  7. Linux启动或重启网卡【命令】
  8. jdk生成keystore、tomcat配置https
  9. html转换为pdf的笔顺,笔顺正确写法,很全面.pdf
  10. 利用Gtihub+Vercel一键部署RSSHub教程(完全免费)
  11. Matlab:16进制excel转2进制mat
  12. NLog NETCore 3.0 Porting
  13. html页面div的显示/隐藏
  14. Java log4j详细教程
  15. 卸载电脑右下角闪烁的游戏图标的教程
  16. java根据经纬度坐标计算两点的距离算法,与百度地图测距工具相符
  17. 【测绘程序设计】——潮汐调和分析
  18. 在arduino中ESP8266的GPIO引脚及控制序号
  19. 关系的基本概念及其性质
  20. Python 求圆的面积

热门文章

  1. shell 踢人办法
  2. Java 实战篇-JDK9新特性
  3. openpythonxl_常用模块之openpyxl (python3入门)
  4. ABP开发框架前后端开发系列---(2)框架的初步介绍
  5. sql:除非另外还指定了 TOP 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询
  6. PHP 根据 搜索条件/勾选数据 分批次 处理数据
  7. LINUX终端可以使用reset清除所有输出
  8. 同样是百度输入法,定制远没有原版好用
  9. mod_signalwire.c:1009 Next SignalWire adoption
  10. OpenJDK8编码代码三合一:x86/Arm/Mips