linux下socket keep alive讲解

摘要:
服务器和客户端套接字设置了keepalive属性。此外,任何想要定期检查连接状态的人都可以启用keepalive。另一端不能被动地响应探测包。此响应是tcp协议的基本要求,与保持活动无关。Linux内核中的测试发现,对于被阻塞的套接字,如果在录制过程中未设置keepalive,即使网络电缆被拔出或断开,录制也将在很长一段时间内不会返回,最长可达17分钟,尽管这段时间比Linux中的默认超时()短得多。从这个角度来看,keepalive在发送时似乎不起作用,原因尚不清楚。

【需求】

不影响服务器处理的前提下,检测客户端程序是否被强制终了。
【现状】
服务器端和客户端的Socket都设定了keepalive属性。
服务器端设定了探测次数等参数,客户端、服务器只是打开了keepalive机能
服务器端起了一个监视线程,利用select来检测socket是否被关闭。。。

下面这是我的一点肤浅理解。

1.关于keep alive

无论windows,还是linux,keepalive就三个参数:

sk->keepalive_probes:探测次数
sk->keepalive_time   探测的超时
sk->keepalive_intvl 探测间隔

linux的路径:/proc/sys/net/ipv4/

对于一个已经建立的tcp连接。如果在keepalive_time时间内双方没有任何的数据包传输,则开启keepalive功能的一端将发送 eepalive数据包,若没有收到应答,则每隔keepalive_intvl时间再发送该数据包,发送keepalive_probes次。一直没有 收到应答,则发送rst包关闭连接。若收到应答,则将计时器清零。例如★:

sk->keepalive_probes = 3;
sk->keepalive_time   = 30;
sk->keepalive_intvl = 1;

意思就是说对于tcp连接,如果一直在socket上有数据来往就不会触发keepalive,但是如果30秒一直没有数据往来,则keep alive开始工作:发送探测包,受到响应则认为网络,是好的,结束探测;如果没有相应就每隔1秒发探测包,一共发送3次,3次后仍没有相应,
就 关闭连接,也就是从网络开始断到你的socket能够意识到网络异常,最多花33秒。但是如果没有设置keep alive,可能你在你的socket(阻塞性)的上面,接收: recv会一直阻塞不能返回,除非对端主动关闭连接,因为recv不知道socket断了。发送:取决于数据量的大小,只要底层协议站的buffer能放 下你的发送数据,应用程序级别的send就会一直成功返回。 直到buffer满,甚至buffer满了还要阻塞一段时间试图等待buffer空闲。所以你对send的返回值的检查根本检测不到失败。开启了keep alive功能,你直接通过发送接收的函数返回值就可以知道网络是否异常。设置的方法(应用层):

int keepalive = 1; // 开启keepalive属性
int keepidle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测
int keepinterval = 5; // 探测时发包的时间间隔为5 秒
int keepcount = 3; // 探测尝试的次数.如果第1次探测包就收到响应了,则后2次的不再发.
setsockopt(rs, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive , sizeof(keepalive ));
setsockopt(rs, SOL_TCP, TCP_KEEPIDLE, (void*)&keepidle , sizeof(keepidle ));
setsockopt(rs, SOL_TCP, TCP_KEEPINTVL, (void *)&keepinterval , sizeof(keepinterval ));
setsockopt(rs, SOL_TCP, TCP_KEEPCNT, (void *)&keepcount , sizeof(keepcount ));

2.select和keep alive的关系

select 是为单个线程使用多个socket而设计的,跟检测连接无关,如果只是检测一个socket的话,没有必要使用select。开了keepalive机能 的话,每次调用recv或send时检查返回值,判断是否出错或为0.如果出错,再检查errno查资料,看哪个或哪几个错误号表示链接断了或不存在就可 以了。

另外,谁想定期检查连接状况,谁就启用keep alive。另一端可以不起,只是被动地对探测包进行响应,这种响应是tcp协议的基本要求,跟keep alive无关。并不需要客户端和服务器端都开启keep alive。

3.测试结果

按照例★的值在一端的socket上开启keep alive,然后阻塞在一个recv或者不停的send,这个时候拔了网线,测试从拔掉网线到recv/send返回失败的时间。

在linux kernel里头的测试发现,对于阻塞型的socket,当recv的时候,如果没有设置keep alive,即使网线拔掉或者ifdown,recv很长时间不会返回,最长达17分钟,虽然这个时间比linux的默认超时时间()短了很多。但是如果 设置了keep alive,基本都在keepalive_time +keepalive_probes*keepalive_intvl =33秒内返回错误。

但是对于循环不停send的socket,当拔掉网线后,会持续一段时间send返 回成功(0~10秒左右,取决 于发送数据的量),然后send阻塞,因为协议层的buffer满了,在等待buffer空闲,大概90秒左右后才会返回错误。由此看来,send的时 候,keep alive似乎没有起到作用,这个原因至今也不清楚。后来通过给send之前设置timer来解决的。

免责声明:文章转载自《linux下socket keep alive讲解》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ueditor使用本地保存,自动恢复上次编辑的内容CentOS 8 Stream 简单的网络配置下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

响应式编程系列(一):什么是响应式编程?reactor入门

响应式编程 系列文章目录 (一)什么是响应式编程?reactor入门 (二)Flux入门学习:流的概念,特性和基本操作 (三)Flux深入学习:流的高级特性和进阶用法 (四)reactor-core响应式api如何测试和调试? (五)Spring reactive: Spring WebFlux的使用 (六)Spring reactive: webClie...

Linux Linux内核参数调优

Linux内核参数调优 by:授客QQ:1033553122 关于调优的建议: 1、出错时,可以查看操作系统日志,可能会找到一些有用的信息 2、尽量不要“批量”修改内核参数,笔者就曾这么干过,结果“调优”后,性能反而下降,事务出错数反而增加,所以,调优的时候可以考虑逐个参数进行调优,然后对比效果。   说明:我也不是很懂,参考自网络整理了下可能需要调整...

node.js的net模块实现socket通信

本文实例讲述了通过node.js的net模块实现nodejs socket服务端和客户端简单通信功能,可以用作客户端对服务端的端口监听以及事件回执。 server端代码 var net = require('net'); //模块引入 var listenPort = 8080;//监听端口 var server = net.createServer(fu...

SIGPIPE

send或者write socket遭遇SIGPIPE信号 当服务器close一个连接时,若client端接着发数据。根据TCP协议的规定,会收到一个RST响应,client再往这个服务器发送数据时,系统会发出一个SIGPIPE信号给进程,告诉进程这个连接已经断开了,不要再写了。 又或者当一个进程向某个已经收到RST的socket执行写操作是,内核向...

Linux netstat命令详解和使用例子(显示各种网络相关信息)

netstat命令用于显示与IP、TCP、UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况。netstat是在内核中访问网络及相关信息的程序,它能提供TCP连接,TCP和UDP监听,进程内存管理的相关报告 原文链接:https://www.jb51.net/LINUXjishu/152405.html 如果你的计算机有时候接收...

socket测试3

20191218 2021-2022-1-diocs-socket测试-3 服务器端 编写好服务器端程序,开启13端口,等待客户机连接 客户端 绑定服务器IP,选择13号端口 服务器端和客户端同步 我编写的代码服务器端会每隔一秒响应时间请求(即屏幕中有多少条记录即查看了多少次时间) 客户端 服务器端 多客户端访问 之前的客户端是用的OpenEuler...