linux下使用TCP存活(keepalive)定时器_keepalive_idletime 头文件-程序员宅基地

技术标签: tcp  variables  Network  linux  服务器  socket  parameters  

2008-05-22 14:34

/*由 hi.baidu.com/zhihui3409 收集整理,转载时请附带 此行*/

 

一、什么是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]

在 此描述中,我们称使用存活选项的那一段为服务器,另一端为客户端。也可以在客户端设置该选项,且没有不允许这样做的理由,但通常设置在服务器。如果连接两 端都需要探测对方是否消失,那么就可以在两端同时设置(比如 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 has built-in support for keepalive. You need to enable TCP/IP networking in order to use it. You also need procfs support and sysctl support to be able to configure the kernel parameters at runtime.

The procedures involving keepalive use three user-driven variables:

 

tcp_keepalive_time

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

tcp_keepalive_intvl

the interval between subsequential keepalive probes, regardless of what the connection has exchanged in the meantime

tcp_keepalive_probes

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_time

7200
# cat /proc/sys/net/ipv4/tcp_keepalive_intvl

75
# cat /proc/sys/net/ipv4/tcp_keepalive_probes 

9

 

 

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]

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 be SO_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_intvl int keepAlive = 1; // 开启keepalive属性

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/codejoker/article/details/5394100

智能推荐

python opencv resize函数_python opencv 等比例调整(缩放)图片分辨率大小代码 cv2.resize()...-程序员宅基地

文章浏览阅读1.3k次。# -*- coding: utf-8 -*-"""@File : 200113_等比例调整图像分辨率大小.py@Time : 2020/1/13 13:38@Author : Dontla@Email : [email protected]@Software: PyCharm"""import cv2def img_resize(image):height, width = image...._opencv小图等比例缩放

【OFDM、OOK、PPM、QAM的BER仿真】绘制不同调制方案的误码率曲线研究(Matlab代码实现)-程序员宅基地

文章浏览阅读42次。对于这些调制技术的误码率(BER)研究是非常重要的,因为它们可以帮助我们了解在不同信道条件下系统的性能表现。通过以上步骤,您可以进行OFDM、OOK、PPM和QAM的误码率仿真研究,并绘制它们的误码率曲线,以便更好地了解它们在不同信道条件下的性能特点。针对这些调制技术的BER研究是非常重要的,可以帮助我们更好地了解这些技术在不同信道条件下的性能表现,从而指导系统设计和优化。6. 分析结果:根据误码率曲线的比较,分析每种调制方案在不同信噪比条件下的性能,包括其容忍的信道条件和适用的应用场景。_ber仿真

【已解决】Vue的Element框架,日期组件(el-date-picker)的@change事件,不会触发。_el-date-picker @change不触发-程序员宅基地

文章浏览阅读2.5w次,点赞3次,收藏3次。1、场景照抄官方的实例,绑定了 myData.Age 这个值。实际选择某个日期后,从 vuetool(开发工具)看,值已经更新了,但视图未更新。2、尝试绑定另一个值: myData,可以正常的触发 @change 方法。可能是:值绑定到子对象时,组件没有侦测到。3、解决使用 @blur 代替 @change 方法。再判断下 “值有没有更新” 即可。如有更好的方法,欢迎评论!..._el-date-picker @change不触发

PCL学习:滤波—Projectlnliers投影滤波_projectinliers-程序员宅基地

文章浏览阅读1.5k次,点赞2次,收藏8次。Projectlnliersclass pcl: : Projectlnliers< PointT >类 Projectlnliers 使用一个模型和一组的内点的索引,将内点投影到模型形成新的一个独立点云。关键成员函数 void setModelType(int model) 通过用户给定的参数设置使用的模型类型 ,参数 Model 为模型类型(见 mo..._projectinliers

未处理System.BadImageFormatException”类型的未经处理的异常在 xxxxxxx.exe 中发生_“system.badimageformatexception”类型的未经处理的异常在 未知模块。 -程序员宅基地

文章浏览阅读2.4k次。“System.BadImageFormatException”类型的未经处理的异常在 xxxx.exe 中发生其他信息: 未能加载文件或程序集“xxxxxxx, Version=xxxxxx,xxxxxxx”或它的某一个依赖项。试图加载格式不正确的程序。此原因是由于 ” 目标程序的目标平台与 依赖项的目标编译平台不一致导致,把所有的项目都修改到同一目标平台下(X86、X64或AnyCPU)进行编译,一般即可解决问题“。若果以上方式不能解决,可采用如下方式:右键选择配置管理器,在这里修改平台。_“system.badimageformatexception”类型的未经处理的异常在 未知模块。 中发生

PC移植安卓---2018/04/26_电脑软件移植安卓-程序员宅基地

文章浏览阅读2.4k次。记录一下碰到的问题:1.Assetbundle加载问题: 原PC打包后的AssetBundle导入安卓工程后,加载会出问题。同时工程打包APK时,StreamingAssets中不能有中文。解决方案: (1).加入PinYinConvert类,用于将中文转换为拼音(多音字可能会出错,例如空调转换为KongDiao||阿拉伯数字不支持,如Ⅰ、Ⅱ、Ⅲ、Ⅳ(IIII)、Ⅴ、Ⅵ、Ⅶ、Ⅷ、Ⅸ、Ⅹ..._电脑软件移植安卓

随便推点

聊聊线程之run方法_start 是同步还是异步-程序员宅基地

文章浏览阅读2.4k次。话不多说参考书籍 汪文君补充知识:start是异步,run是同步,start的执行会经过JNI方法然后被任务执行调度器告知给系统内核分配时间片进行创建线程并执行,而直接调用run不经过本地方法就是普通对象执行实例方法。什么是线程?1.现在几乎百分之百的操作系统都支持多任务的执行,对计算机来说每一个人物就是一个进程(Process),在每一个进程内部至少要有一个线程实在运行中,有时线..._start 是同步还是异步

制作非缘勿扰页面特效----JQuery_单击标题“非缘勿扰”,<dd>元素中有id属性的<span>的文本(主演、导演、标签、剧情-程序员宅基地

文章浏览阅读5.3k次,点赞9次,收藏34次。我主要用了层次选择器和属性选择器可以随意选择,方便简单为主大体CSS格式 大家自行构造网页主体<body> <div class='main' > <div class='left'> <img src="images/pic.gif" /> <br/><br/> <img src="images/col.gif" alt="收藏本片"/&_单击标题“非缘勿扰”,元素中有id属性的的文本(主演、导演、标签、剧情

有了这6款浏览器插件,浏览器居然“活了”?!媳妇儿直呼“大开眼界”_浏览器插件助手-程序员宅基地

文章浏览阅读901次,点赞20次,收藏23次。浏览器是每台电脑的必装软件,去浏览器搜索资源和信息已经成为我们的日常,我媳妇儿原本也以为浏览器就是上网冲浪而已,哪有那么强大,但经过我的演示之后她惊呆了,直接给我竖起大拇指道:“原来浏览器还能这么用?大开眼界!今天来给大家介绍几款实用的浏览器插件,学会之后让你的浏览器“活过来”!_浏览器插件助手

NumPy科学数学库_数学中常用的环境有numpy-程序员宅基地

文章浏览阅读101次。NumPy是Python中最常用的科学数学计算库之一,它提供了高效的多维数组对象以及对这些数组进行操作的函数NumPy的核心是ndarray(N-dimensional array)对象,它是一个用于存储同类型数据的多维数组Numpy通常与SciPy(Scientific Python)和 Matplotlib(绘图库)一起使用,用于替代MatLabSciPy是一个开源的Python算法库和数学工具包;Matplotlib是Python语言及其Numpy的可视化操作界面'''_数学中常用的环境有numpy

dind(docker in docker)学习-程序员宅基地

文章浏览阅读1.1w次。docker in docker说白了,就是在docker容器内启动一个docker daemon,对外提供服务。优点在于:镜像和容器都在一个隔离的环境,保持操作者的干净环境。想到了再补充 :)一:低版本启动及访问启动1.12.6-dinddocker run --privileged -d --name mydocker docker:1.12.6-dind在其他容器访问d..._dind

推荐文章

热门文章

相关标签