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

智能推荐

使用UmcFramework和unimrcpclient.xml连接多个SIP设置的配置指南及C代码示例

在多媒体通信领域,MRCP(Media Resource Control Protocol)协议被广泛用于控制语音识别和合成等媒体资源。UniMRCP是一个开源的MRCP实现,提供了客户端和服务端的库。UmcFramework是一个基于UniMRCP客户端库的示例应用程序框架,它帮助开发者快速集成和测试MRCP客户端功能。本文将详细介绍如何使用UmcFramework和unimrcpclient.xml配置文件连接到多个SIP设置,以及如何用C代码进行示例说明。

java.net.ProtocolException: Server redirected too many times (20)-程序员宅基地

文章浏览阅读3k次。报错:java.net.ProtocolException: Server redirected too many times (20)1.没有检查到cookie,一直循环重定向。解决:CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));URL url = new URL(url); ..._java.net.protocolexception: server redirected too many times (20)

springboot启动报错 Failed to scan *****/derbyLocale_ja_JP.jar from classloader hierarchy_failed to scan from classloader hierarchy-程序员宅基地

文章浏览阅读4.1k次。问题这是部分报错信息2019-07-11 14:03:34.283 WARN [restartedMain][DirectJDKLog.java:175] - Failed to scan [file:/D:/repo/org/apache/derby/derby/10.14.2.0/derbyLocale_ja_JP.jar] from classloader hierarchyjava...._failed to scan from classloader hierarchy

MATLAB-ones函数_matlab中ones函数-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏7次。在MATLAB中,ones函数用于创建一个指定大小的由1组成的矩阵或数组。_matlab中ones函数

解决PS等软件出现应用程序无法正常启动(0xc000007b)_photoshop应用程序无法正常启动0xc000007b。请单击“确认”关闭应用程序。-程序员宅基地

文章浏览阅读3.9w次,点赞2次,收藏9次。  在使用电脑办公过程中,安装应用程序时难免遇到无法安装或者无法正常启动的问题,这对我们使用电脑带来了诸多不便。那遇到应用程序无法正常启动的问题要如何解决呢?相信大家肯定都是十分疑问的,每次都是只能忍痛重新安装软件。今天,小编就和大家探讨下应用程序无法正常启动的解决方法,帮助大家排忧解难。0xc000007b电脑图解1  第一种方案:SFC检查系统完整性来尝试修复丢失文件  1、打开电脑搜索输入cmd.exe,选择以管理员身份运行,跳出提示框时选择继续。0xc000007b电脑图解2_photoshop应用程序无法正常启动0xc000007b。请单击“确认”关闭应用程序。

oracle介质恢复和实例恢复的异同-程序员宅基地

文章浏览阅读396次。1、概念 REDO LOG是Oracle为确保已经提交的事务不会丢失而建立的一个机制。实际上REDO LOG的存在是为两种场景准备的:实例恢复(INSTANCE RECOVERY);介质恢复(MEDIA RECOVERY)。 实例恢复的目的是在数据库发生故障时,确保BUFFER CACHE中的数据不会丢失,不会造成数据库的..._oracle 实例恢复和介质恢复

随便推点

轻松搭建CAS 5.x系列(5)-增加密码找回和密码修改功能-程序员宅基地

文章浏览阅读418次。概述说明CAS内置了密码找回和密码修改的功能; 密码找回功能是,系统会吧密码重置的连接通过邮件或短信方式发送给用户,用户点击链接后就可以重置密码,cas还支持预留密码重置的问题,只有回答对了,才可以重置密码;系统可配置密码重置后,是否自动登录; 密码修改功能是,用户登录后输入新密码即可完成密码修改。安装步骤`1. 首先,搭建好cas sso server您需要按..._修改cas默认用户密码

springcloud(七) feign + Hystrix 整合 、-程序员宅基地

文章浏览阅读141次。之前几章演示的熔断,降级 都是 RestTemplate + Ribbon 和RestTemplate + Hystrix ,但是在实际开发并不是这样,实际开发中都是 Feign 远程接口调用。Feign + Hystrix 演示:  eruka(略)order 服务工程:  pom.xml<?xml version="1.0" encoding="U..._this is order 服务工程

YOLOv7如何提高目标检测的速度和精度,基于优化算法提高目标检测速度-程序员宅基地

文章浏览阅读3.4k次,点赞35次,收藏43次。学习率是影响目标检测精度和速度的重要因素之一。合适的学习率调度策略可以加速模型的收敛和提高模型的精度。在YOLOv7算法中,可以使用基于余弦函数的学习率调度策略(Cosine Annealing Learning Rate Schedule)来调整学习率。

linux中进程退出函数:exit()和_exit()的区别_linux结束进程可以用哪些函数,它们之间有何区别?-程序员宅基地

文章浏览阅读4k次,点赞4次,收藏9次。 linux中进程退出函数:exit()和_exit()的区别(1)_exit()执行后立即返回给内核,而exit()要先执行一些清除操作,然后将控制权交给内核。(2)调用_exit函数时,其会关闭进程所有的文件描述符,清理内存以及其他一些内核清理函数,但不会刷新流(stdin, stdout, stderr ...). exit函数是在_exit..._linux结束进程可以用哪些函数,它们之间有何区别?

sqlserver55555_sqlserver把小数点后面多余的0去掉-程序员宅基地

文章浏览阅读134次。select 5000/10000.0 --想变成0.5select 5500/10000.0 --想变成0.55select 5550/10000.0 --想变成0.555select 5555/10000.0 --想变成0.5555其结果分别为:0.5000000 0.5500000 0.5550000 0.5555000一、如果想去掉数字5后面多余的0 ,需要转化一下:selec..._sql server 去小数 0

Angular6 和 RXJS6 的一些改动_angular6,requestoptions改成了什么-程序员宅基地

文章浏览阅读3.1k次。例一:import { Injectable } from '@angular/core';import { Observable } from 'rxjs';import { User } from "./model/User";import { map } from 'rxjs/operators';import { Http, Response, Headers, RequestOp..._angular6,requestoptions改成了什么

推荐文章

热门文章

相关标签