TCP长连接(Keepalive)

2023-05-16

TCP Keepalive的起源
TCP协议中有长连接和短连接之分。短连接环境下,数据交互完毕后,主动释放连接;

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

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服务器框架中也提供了相关接口。

TCP Keepalive作用
1.     探测连接的对端是否存活

在应用交互的过程中,可能存在以下几种情况:

    (1)客户端或服务器意外断电,死机,崩溃,重启。

    (2)中间网络已经中断,而客户端与服务器并不知道。

       利用保活探测功能,可以探知这种对端的意外情况,从而保证在意外发生时,可以释放半打开的TCP连接。

2.     防止中间设备因超时删除连接相关的连接表

    中间设备如防火墙等,会为经过它的数据报文建立相关的连接信息表,并为其设置一个超时时间的定时器,如果超出预定时间,某连接无任何报文交互的话,

中间设备会将该连接信息从表中删除,在删除后,再有应用报文过来时,中间设备将丢弃该报文,从而导致应用出现异常。

此段参考:https://www.cnblogs.com/hukey/p/5481173.html

TCP Keepalive可能导致的问题
Keepalive 技术只是 TCP 技术中的一个可选项。因为不当的配置可能会引起一些问题,所以默认是关闭的。

可能导致下列问题:

1.     在短暂的故障期间,Keepalive设置不合理时可能会因为短暂的网络波动而断开健康的TCP连接

2.     需要消耗额外的宽带和流量

3.     在以流量计费的互联网环境中增加了费用开销

TCP Keepalive HTTP Keep-Alive 的关系
很多人会把TCP Keepalive 和 HTTP Keep-Alive 这两个概念搞混淆。

这里简单介绍下HTTP Keep-Alive 。

在HTTP/1.0中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。如果客户端浏览器访问的某个HTML或其他类型的 Web页中包含有其他的Web资源,如JavaScript文件、图像文件、CSS文件等;当浏览器每遇到这样一个Web资源,就会建立一个HTTP会话。

但从 HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头加上Connection、Keep-Alive字段.如下图所示

HTTP 1.0 和 1.1 在 TCP连接使用方面的差异如下图所示

上面说明后,其实就可以知道这两者的区别了。

长/短连接的优点和缺点

  • 长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。
    对于频繁请求资源的客户来说,较适用长连接。

  • 不过这里存在一个问题,存活功能的探测周期太长,还有就是它只是探测TCP连接的存活,
    属于比较斯文的做法,遇到恶意的连接时,保活功能就不够使了。
    在长连接的应用场景下,client端一般不会主动关闭它们之间的连接,
    client与server之间的连接如果一直不关闭的话,会存在一个问题,
    随着客户端连接越来越多,server早晚有扛不住的时候,这时候server端需要采取一些策略,
    如关闭一些长时间没有读写事件发生的连接,这样可以避免一些恶意连接导致server端服务受损;
    如果条件再允许就可以以客户端机器为颗粒度,限制每个客户端的最大长连接数,
    这样可以完全避免某个蛋疼的客户端连累后端服务。

  • 短连接对于服务器来说管理较为简单,存在的连接都是有用的连接,不需要额外的控制手段。

  • 但如果客户请求频繁,将在TCP的建立和关闭操作上浪费时间和带宽。

长/短连接的应用场景

  • 长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况。
    每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,
    再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,
    再次处理时直接发送数据包就OK了,不用建立TCP连接。
    例如:数据库的连接用长连接,如果用短连接频繁的通信会造成socket错误,
    而且频繁的socket 创建也是对资源的浪费。

  • 而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,
    而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,
    如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,
    那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。



作者:乾九二
链接:https://www.jianshu.com/p/313798ae863d
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

HTTP协议的Keep-Alive意图在于TCP连接复用,同一个连接上串行方式传递请求-响应数据;TCP的Keepalive机制意图在于探测连接的对端是否存活。
————————————————
版权声明:本文为CSDN博主「chrisnotfound」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/chrisnotfound/article/details/80111559

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TCP长连接(Keepalive) 的相关文章

  • Node.js 找不到模块“tcp”

    节点在以下行崩溃 var tcp require tcp 错误文本 node js 201 throw e process nextTick error or error event on first tick Error Cannot f
  • retrbinary 期间线程化“NOOP”命令

    我编写了一个 FTP 脚本 遗憾的是该脚本必须处理位于防火墙后面的服务器 ISP 也会很早就切断我的控制连接 无论我在防火墙的任一侧设置什么样的超时设置 我最终做出了两个选择 1 在 retrbinary 命令中分叉代码 以便下载完成时每
  • TCP 兼容性:为什么 TCP 不兼容数据包广播和组播操作?

    http en wikipedia org wiki User Datagram Protocol http en wikipedia org wiki User Datagram Protocol 与 TCP 不同 UDP 与数据包广播
  • Socket ReceiveAsync 合并数据包

    我打算通过套接字接收数据包 但由于它们是从发送方以高频率发送的 因此其中许多数据包被打包成一个byte array SocketAsyncEventArgs Buffer然后保存多个数据包 即使它们是单独发送的 使用验证wireshark
  • 使用 iPhone 作为热点时 TCP 连接无法正常工作

    我正在开发一个 iOS 应用程序 它通过 TCP 套接字连接到在 Android 上运行的服务器应用程序 为了找到第二个设备的 IP 我使用 UDP 请求并接收服务器的 IP 当我将它们连接到 Wi Fi 网络或使用 Android 设备作
  • Scapy 不需要的 RST TCP 数据包

    为了理解TCP是如何工作的 我尝试伪造自己的TCP SYN SYN ACK ACK 基于教程 http www thice nl creating ack get packets with scapy http www thice nl c
  • 在 Perl 中如何接受多个 TCP 连接?

    我对 Linux 的 Perl 脚本有疑问 它的主要目的是成为 3 个应用程序之间的中间人 它应该做什么 它应该能够等待 UDP 文本 不带空格 udp port 当它收到 UDP 文本时 它应该将其转发到连接的 TCP 客户端 问题是我的
  • PHP 上的多个 TCP 套接字请求

    是否可以使用 PHP 上的套接字服务器接受多个请求 并行 如果可以的话 怎样做 普通的 PHP 脚本无法接收多个请求 但如果你真的计划创建一个套接字服务器 作为 cmdline php 脚本启动 那么是的 这是可能的 调查http pear
  • 为什么我们可以将 sockaddr 转换为 sockaddr_in

    我明白为什么强制转换很有用sockaddr to sockaddr in 但我不明白这怎么可能 据我所知 它们的大小相同sockaddr in添加了sin zero使其大小相同 我想知道编译器如何知道从哪里获取信息sockaddr in如果
  • 使用 HttpClient 的 HTTP 请求太慢?

    我正在尝试编写一个 Android 应用程序 将一些发布值发送到托管在专用服务器上的 php 文件并存储数组结果 代码是这样的 HttpPost httppost DefaultHttpClient httpclient httppost
  • 发起TCP连接关闭后如何接收数据?

    TCP 允许一侧发出 FIN 并让另一侧在结束其一侧的连接之前响应一些数据 我如何使用 NET 来实现这一点TcpClient 看来我必须使用Close发出FIN 但之后我不能再打电话Client Receive since Client被
  • Ruby 守护进程,用于使临时 Ruby 实例的对象保持活动状态

    Ruby 是否提供了一种在不同运行的 Ruby 进程之间共享变量 更重要的是 类对象和我认为对此有用的任何其他数据抽象 的机制 例如 如果我有一个类被实例化 初始化并仔细调整到某种状态 我希望该状态对我全天所有其他独立的 Ruby 和 Ir
  • 无法分配请求的地址 - 可能的原因?

    我有一个由主服务器和分布式从服务器组成的程序 从属服务器向服务器发送状态更新 如果服务器在固定时间内没有收到特定从属服务器的消息 则会将该从属服务器标记为关闭 这种情况一直在发生 通过检查日志 我发现从站只能向服务器发送一个状态更新 然后永
  • 服务器响应中的“连接:保持活动状态”

    我正在尝试建立从 Silverlight 应用程序到 Apache 服务器托管的 PHP 页面的 HTTP 持久连接 即无需为每个 HTTP 请求创建新的 TCP 连接 为此 我需要网络服务器发送其 HTTP 响应 并将 Connectio
  • 使用 boost 异步发送和接收自定义数据包?

    我正在尝试使用 boost 异步发送和接收自定义数据包 根据我当前的实现 我有一些问题 tcpclient cpp include tcpclient h include
  • 当使用环回地址使用 TCP/IP 套接字进行 IPC 时,常见的网络堆栈是否会跳过将消息帧封装在较低级别的 PDU 中?

    在某些环境 例如 Java 中 很自然地使用 TCP IP 套接字通过 localhost 地址 IPv4 中的 127 0 0 1 或 IPv6 中的 1 在同一主机上的进程之间传递消息 因为Java倾向于不在其API中公开其他IPC机制
  • UWP 无法在两个应用程序之间创建本地主机连接

    我正在尝试在两个 UWP 应用程序之间设置 TCP 连接 当服务器和客户端在同一个应用程序中运行时 它可以正常工作 但是 当我将服务器部分移动到一个应用程序并将客户端部分移动到另一个应用程序时 ConnectAsync 会引发异常 服务器未
  • Erlang gen_tcp 连接问题

    简单的问题 这段代码 client gt SomeHostInNet localhost to make it runnable on one machine ok Sock gen tcp connect SomeHostInNet 56
  • 建立 TCP 连接边界的正确方法

    我的问题是关于如何正确处理使用 tcp 连接接收的数据 事实上 通过建立 tcp 连接 创建了一个流 假设我想发送一条有开头和结尾的消息 由于数据在流中流动而没有指定任何边界 我如何识别消息的开始和结束 我想在消息的开头和结尾处放置一些特殊
  • 如何使用 Nmap 检索 TCP 和 UDP 端口? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我需要在使用 Nmap 的同一扫描中以尽可能最快的方式检索 TCP 和 UDP 端口 我会尽力解释得更好 如果我使用最常用的命令 nmap 192 1

随机推荐