这两天服务器网络不稳定,结果发现了一个现象:一个TCP连接的服务端(windows)早已停止,而客户端(linux)的连接状态却一直保持为ESTABLISHED,直到第二天中午连接才断开。在网上搜一下,才知道TCP的相关设置:
#cat /proc/sys/net/ipv4/tcp_keepalive_time
7200
#cat /proc/sys/net/ipv4/tcp_keepalive_intvl
75
#cat /proc/sys/net/ipv4/tcp_keepalive_probes
9
意思是如果某个TCP连接在idle 7200秒(2个小时)后,内核才发起probe.如果probe 9次(每次75秒)不成功,内核才彻底放弃,认为该连接已失效。
2*9=18小时,这就是为什么前一天下午网络出问题,到第二天中午那个连接才显示关掉。
下面转一点详细的知识:
一、什么是keepalive定时器?[1]
在一个空闲的(idle)TCP连接上,没有任何的数据流,许多TCP/IP的初学者都对此感到惊奇。也就是说,如果TCP连接两端没有任何一个进程在向对方发送数据,那么在这两个TCP模块之间没有任何的数据交换。你可能在其它的网络协议中发现有轮询(polling),但在TCP中它不存在。言外之意就是我们只要启动一个客户端进程,同服务器建立了TCP连接,不管你离开几小时,几天,几星期或是几个月,连接依旧存在。中间的路由器可能崩溃或者重启,电话线可能go down或者back up,只要连接两端的主机没有重启,连接依旧保持建立。
这就可以认为不管是客户端的还是服务器端的应用程序都没有应用程序级(application-level)的定时器来探测连接的不活动状态(inactivity),从而引起任何一个应用程序的终止。然而有的时候,服务器需要知道客户端主机是否已崩溃并且关闭,或者崩溃但重启。许多实现提供了存活定时器来完成这个任务。
存活定时器是一个包含争议的特征。许多人认为,即使需要这个特征,这种对对方的轮询也应该由应用程序来完成,而不是由TCP中实现。此外,如果两个终端系统之间的某个中间网络上有连接的暂时中断,那么存活选项(option)就能够引起两个进程间一个良好连接的终止。例如,如果正好在某个中间路由器崩溃、重启的时候发送存活探测,TCP就将会认为客户端主机已经崩溃,但事实并非如此。
存活(keepalive)并不是TCP规范的一部分。在Host Requirements RFC罗列有不使用它的三个理由:(1)在短暂的故障期间,它们可能引起一个良好连接(good connection)被释放(dropped),(2)它们消费了不必要的宽带,(3)在以数据包计费的互联网上它们(额外)花费金钱。然而,在许多的实现中提供了存活定时器。
一些服务器应用程序可能代表客户端占用资源,它们需要知道客户端主机是否崩溃。存活定时器可以为这些应用程序提供探测服务。Telnet服务器和Rlogin服务器的许多版本都默认提供存活选项。
个人计算机用户使用TCP/IP协议通过Telnet登录一台主机,这是能够说明需要使用存活定时器的一个常用例子。如果某个用户在使用结束时只是关掉了电源,而没有注销(log off),那么他就留下了一个半打开(half-open)的连接。在图18.16,我们看到如何在一个半打开连接上通过发送数据,得到一个复位(reset)返回,但那是在客户端,是由客户端发送的数据。如果客户端消失,留给了服务器端半打开的连接,并且服务器又在等待客户端的数据,那么等待将永远持续下去。存活特征的目的就是在服务器端检测这种半打开连接。
二、keepalive如何工作?[1]
二、keepalive如何工作?[1]
在此描述中,我们称使用存活选项的那一段为服务器,另一端为客户端。也可以在客户端设置该选项,且没有不允许这样做的理由,但通常设置在服务器。如果连接两端都需要探测对方是否消失,那么就可以在两端同时设置(比如NFS)。
若在一个给定连接上,两小时之内无任何活动,服务器便向客户端发送一个探测段。(我们将在下面的例子中看到探测段的样子。)客户端主机必须是下列四种状态之一:
1) 客户端主机依旧活跃(up)运行,并且从服务器可到达。从客户端TCP的正常响应,服务器知道对方仍然活跃。服务器的TCP为接下来的两小时复位存活定时器,如果在这两个小时到期之前,连接上发生应用程序的通信,则定时器重新为往下的两小时复位,并且接着交换数据。
2) 客户端已经崩溃,或者已经关闭(down),或者正在重启过程中。在这两种情况下,它的TCP都不会响应。服务器没有收到对其发出探测的响应,并且在75秒之后超时。服务器将总共发送10个这样的探测,每个探测75秒。如果没有收到一个响应,它就认为客户端主机已经关闭并终止连接。
3) 客户端曾经崩溃,但已经重启。这种情况下,服务器将会收到对其存活探测的响应,但该响应是一个复位,从而引起服务器对连接的终止。
4) 客户端主机活跃运行,但从服务器不可到达。这与状态2类似,因为TCP无法区别它们两个。它所能表明的仅是未收到对其探测的回复。
服务器不必担心客户端主机被关闭然后重启的情况(这里指的是操作员执行的正常关闭,而不是主机的崩溃)。当系统被操作员关闭时,所有的应用程序进程(也就是客户端进程)都将被终止,客户端TCP会在连接上发送一个FIN。收到这个FIN后,服务器TCP向服务器进程报告一个文件结束,以允许服务器检测这种状态。
在第一种状态下,服务器应用程序不知道存活探测是否发生。凡事都是由TCP层处理的,存活探测对应用程序透明,直到后面2,3,4三种状态发生。在这三种状态下,通过服务器的TCP,返回给服务器应用程序错误信息。(通常服务器向网络发出一个读请求,等待客户端的数据。如果存活特征返回一个错误信息,则将该信息作为读操作的返回值返回给服务器。)在状态2,错误信息类似于“连接超时”。状态3则为“连接被对方复位”。第四种状态看起来像连接超时,或者根据是否收到与该连接相关的ICMP错误信息,而可能返回其它的错误信息。
三、在Linux中如何使用keepalive?[2]
三、在Linux中如何使用keepalive?[2]
Linux has built-in support for keepalive. You need to enable TCP/IP networking in order to use it. You also need procfs support andsysctl support to be able to configure the kernel parameters at runtime.
The procedures involving keepalive use three user-driven variables:
the interval between the last data packet sent (simple ACKs are not considered data) and the first keepalive probe; after the connection is marked to need keepalive, this counter is not used any further
the interval between subsequential keepalive probes, regardless of what the connection has exchanged in the meantime
the number of unacknowledged probes to send before considering the connection dead and notifying the application layer
Remember that keepalive support, even if configured in the kernel, is not the default behavior in Linux. Programs must request keepalive control for their sockets using the setsockopt interface. There are relatively few programs implementing keepalive, but you can easily add keepalive support for most of them following the instructions.
上面一段话已经说得很明白,linux内核包含对keepalive的支持。其中使用了三个参数:tcp_keepalive_time(开启keepalive的闲置时长)tcp_keepalive_intvl(keepalive探测包的发送间隔) 和tcp_keepalive_probes (如果对方不予应答,探测包的发送次数);如何配置这三个参数呢?
There are two ways to configure keepalive parameters inside the kernel via userspace commands:
-
procfs interface
-
sysctl interface
We mainly discuss how this is accomplished on the procfs interface because it's the most used, recommended and the easiest to understand. The sysctl interface, particularly regarding the sysctl(2) syscall and not the sysctl(8) tool, is only here for the purpose of background knowledge.
The procfs interface
This interface requires both sysctl and procfs to be built into the kernel, and procfs mounted somewhere in the filesystem (usually on/proc, as in the examples below). You can read the values for the actual parameters by "catting" files in /proc/sys/net/ipv4/directory:
# cat /proc/sys/net/ipv4/tcp_keepalive_time7200# cat /proc/sys/net/ipv4/tcp_keepalive_intvl75# cat /proc/sys/net/ipv4/tcp_keepalive_probes9
|
The first two parameters are expressed in seconds, and the last is the pure number. This means that the keepalive routines wait for two hours (7200 secs) before sending the first keepalive probe, and then resend it every 75 seconds. If no ACK response is received for nine consecutive times, the connection is marked as broken.
Modifying this value is straightforward: you need to write new values into the files. Suppose you decide to configure the host so that keepalive starts after ten minutes of channel inactivity, and then send probes in intervals of one minute. Because of the high instability of our network trunk and the low value of the interval, suppose you also want to increase the number of probes to 20.
Here's how we would change the settings:
# echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time# echo 60 > /proc/sys/net/ipv4/tcp_keepalive_intvl# echo 20 > /proc/sys/net/ipv4/tcp_keepalive_probes
|
To be sure that all succeeds, recheck the files and confirm these new values are showing in place of the old ones.
这样,上面的三个参数配置完毕。使这些参数重启时保持不变的方法请阅读参考文献[2]。
四、在程序中如何使用keepalive?[2]-[4]
四、在程序中如何使用keepalive?[2]-[4]
All you need to enable keepalive for a specific socket is to set the specific socket option on the socket itself. The prototype of the function is as follows:
int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) |
The first parameter is the socket, previously created with the socket(2); the second one must be SOL_SOCKET, and the third must beSO_KEEPALIVE . The fourth parameter must be a boolean integer value, indicating that we want to enable the option, while the last is the size of the value passed before.
According to the manpage, 0 is returned upon success, and -1 is returned on error (and errno is properly set).
There are also three other socket options you can set for keepalive when you write your application. They all use the SOL_TCP level instead of SOL_SOCKET, and they override system-wide variables only for the current socket. If you read without writing first, the current system-wide parameters will be returned.
-
TCP_KEEPCNT: overrides tcp_keepalive_probes
-
TCP_KEEPIDLE: overrides tcp_keepalive_time
-
TCP_KEEPINTVL: overrides tcp_keepalive_intvlint keepAlive = 1; // 开启keepalive属性我们看到keepalive是一个开关选项,可以通过函数来使能。具体地说,可以使用以下代码:setsockopt(rs, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));上面英文资料中提到的第二个参数可以取为SOL_TCP,以设置keepalive的三个参数(具体代码参考文献[3]),在程序中实现需要头文件“netinet/tcp.h”。当然,在实际编程时也可以采用系统调用的方式配置的keepalive参数。关于setsockopt的其他参数可以参考文献[4]。
五、如何判断TCP连接是否断开?[3]当tcp检测到对端socket不再可用时(不能发出探测包,或探测包没有收到ACK的响应包),select会返回socket可读,并且在recv时返回-1,同时置上errno为ETIMEDOUT。
相关推荐
Linux 下 TCP 连接迁移技术是一种基于 TCP 连接迁移的负载均衡方法,它可以将一个 TCP 连接的一个端点迁移到另一个节点,而整个迁移过程对于连接的另一端点来说是透明的。这种技术可以大大减轻前端服务器的负担,...
关于TCP服务器最大并发连接数有一种误解就是“因为端口号上限为65535,所以TCP服务器理论上的可承载的最大并发连接数也是65535”。 先说结论:对于TCP服务端进程来说,他可以同时连接的客户端数量并不受限于可用端口...
这种技术允许TCP连接在不被客户端感知的情况下,从一个节点迁移到另一个节点,以实现负载均衡。在Linux环境下,TCP连接迁移的实现涉及到对TCP/IP协议栈的深入理解和定制。 【Linux TCP/IP协议栈】 Linux操作系统...
3. **创建Modbus上下文**:使用`modbus_new_tcp()`函数创建一个新的Modbus TCP上下文,这是所有Modbus操作的基础。 4. **连接到Modbus服务器**:使用`modbus_connect()`函数,指定服务器的IP地址和端口号(Modbus...
【Linux网络编程笔记】TCP短连接产生大量TIME_WAIT导致无法对外建立新TCP连接的原因及解决方法,这是一个关于网络编程和Linux系统配置的问题。在TCP/IP通信中,TIME_WAIT状态是TCP连接生命周期的一部分,用于确保...
无论是Linux还是Windows操作系统,开发者都需要了解如何判断一个Socket连接的状态,以便于处理异常情况,保证程序的稳定性和可靠性。本文将深入探讨在Linux和Windows环境下,如何通过编程来检测Socket连接是否已断开...
1 检测web服务器的链接数量及状态: netstat -ant|awk '{print $5 \t $6}'|grep ::ffff:|sed -e 's/::ffff://' -e 's/:[0-9]*//' |sort|uniq -c| sort -rn|head -10 结果: 122 125.162.71.199 TIME_WAIT ...
【Python-tcpkiller用于在Linux或macOS上关闭一个TCP连接】 Python-tcpkiller是一个实用的工具,专门设计用于在Linux或macOS操作系统上中断特定的TCP连接。它利用了低级别的socket接口和操作系统的网络控制功能,...
总的来说,Linux TCP服务器压力测试是一个复杂的过程,涉及多方面的知识,包括网络协议、服务器性能优化、系统监控和测试工具的使用。理解这些概念和方法,将帮助你构建更加健壮、高效的TCP服务。
标题提及的Linux设备TCP连接高危漏洞主要涉及的是TCP连接的安全性问题,这个问题对所有接入网络的Linux设备都构成威胁。TCP(传输控制协议)是互联网通信的核心协议之一,负责建立和维护可靠的双向数据流。当设备...
"Window下杀掉TCP连接"这个话题涉及到的是如何管理和终止系统中的TCP(传输控制协议)连接。TCP是互联网协议的一部分,负责在两台设备之间建立可靠的数据传输通道。以下是一些关于在Windows中关闭TCP连接的重要知识...
TCPCP(TCP Connection Passing)是一种基于 TCP 连接迁移的技术,它可以将一个 TCP 连接的一个端点从一台 Linux 主机迁移到另一台 Linux 主机上。整个迁移过程对于连接的另一端来说是透明的,不需要重新建立连接。 ...
### Linux TCP服务器连接时发不出数据问题分析 #### 背景概述 本文主要探讨了在Linux环境下,当TCP服务器与客户端建立连接后,服务器在某些情况下无法向客户端正常发送数据的问题。具体场景为:服务器与两个客户端...
TIME_WAIT状态是TCP连接中一个特殊的状态,它在连接关闭后还会持续一段时间,以防止延迟的数据包导致错误的连接重建。 除了核心代码之外,Linux内核中还包含了BSD Socket层和Inet层的非核心代码分析。在BSD Socket...
在Linux系统如何修改TCP连接数,文件数限制修改、网络端口限制修改;修改用户进程可打开文件数限制;修改网络内核对TCP连接的有关限制;使用支持高并发网络I/O的编程技术
TCP连接数指的是同一时间一个计算机系统通过TCP协议能够建立的并发连接的数量。这个值通常受到操作系统、硬件资源和配置参数的影响。了解如何设置和查看TCP连接数对于网络管理员和开发者来说是至关重要的,因为它...
在IT领域,网络通信是计算机科学的一个重要组成部分,而TCP(传输控制协议)作为网络通信中的主力协议,尤其在Linux操作系统中扮演着至关重要的角色。本文将深入探讨Linux下的TCP编程,包括TCP套接字(socket)的...
当客户端连接到服务器后,它们可以建立一个TCP连接,通过这个连接进行数据的双向传输,例如文件的发送和接收。 下面我们将详细讨论以下几个关键知识点: 1. **TCP连接建立**:TCP连接遵循三次握手的过程,包括SYN...
- **传输层**:TCP(传输控制协议)和UDP(用户数据报协议)是这一层的两个主要协议。 - **网络层**:IP(互联网协议)是这一层的主要协议。 - **链路层**:处理物理地址和数据包的封装与解封。 #### 2. 主要协议...
Linux 4.4.0 内核源码分析 TCP ...Linux 4.4.0 内核源码中 TCP 实现是一个复杂的系统,它涉及到多个组件、函数和数据结构。理解 Linux 4.4.0 内核源码中 TCP 实现需要对 Linux 操作系统内核源码有深入的了解和理解。