【转】Linux下socket keep alive讲解
【需求】
不影响服务器处理的前提下,检测客户端程序是否被强制终了。
【现状】
服务器端和客户端的Socket都设定了keepalive属性。
服务器端设定了探测次数等参数,客户端、服务器只是打开了keepalive机能
服务器端起了一个监视线程,利用select来检测socket是否被关闭。。。
下面这是我的一点肤浅理解。
1.关于keep alive
无论windows,还是linux,keepalive就三个参数:
sk->keepalive_probes:探测次数
sk->keepalive_time
探测的超时
sk->keepalive_intvl 探测间隔
对
于一个已经建立的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讲解的更多相关文章
- linux下socket keep alive讲解
[需求] 不影响服务器处理的前提下,检测客户端程序是否被强制终了.[现状]服务器端和客户端的Socket都设定了keepalive属性.服务器端设定了探测次数等参数,客户端.服务器只是打开了keepa ...
- Linux下socket编程基本知识
本文档主要讲解了Linux下socket编程的一些基本知识,主要包括套接字和字节序的概念,以及一些常用的结构体和函数. 本文是在网易云课堂学习过程中的记录,这个老师讲得很不错,推荐大家围观. Linu ...
- Linux下Socket编程的端口问题( Bind error: Address already in use )
Linux下Socket编程的端口问题( Bind error: Address already in use ) 在进行linux网络编程时,每次修改了源代码并再次编译运行时,常遇到下面的地使用错误 ...
- linux下socket编程实例
linux下socket编程实例一.基本socket函数Linux系统是通过提供套接字(socket)来进行网络编程的.网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符.s ...
- linux下socket编程
相关结构 //下边这两个结构定义在<sys/types.h>里 //一般的地址结构,只能用于覆盖(把其他地址转换为此类型),且只能引用该地址的sa_family字段 struct sock ...
- Linux 下socket通信终极指南(附TCP、UDP完整代码)
linux下用socket通信,有TCP.UDP两种协议,网上的很多教程把两个混在了一起,或者只讲其中一种.现在我把自己这两天研究的成果汇总下来,写了一个完整的,适合初学者参考,也方便自己以后查阅. ...
- c++ 网络编程(七) LINUX下 socket编程 基于套接字的标准I/O函数使用 与 fopen,feof,fgets,fputs函数用法
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9614820.html 一.标准I/O 1,什么是标准I/O?其实是指C语言里的文件操作函数,如 ...
- LInux下socket编程学习笔记
1.socket套接字: socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模 ...
- linux下socket connect 阻塞方式 阻塞时间控制
同事今天问我,如何在linux下的c代码里面控制connect的阻塞时间.应用的背景是:linux下的c程序有两个目标IP需要connect,如果用阻塞方式,当其中一个IP不能连接的情况下,程序将阻塞 ...
随机推荐
- JAVA获取oracle中sequences的最后一个值
项目中,用到一个序列作单号,框架用的是ssh,在dao层去拿的时候,运行时报错为dual is not mapped,[select *.nextval nextvalue from dual] 后来 ...
- 前端开发利器—FIDDLER 转
http://www.cnblogs.com/yuzhongwusan/archive/2012/07/20/2601306.html 前端开发利器—FIDDLER 1.Fiddler相对其他调试工具 ...
- Javascript:一个优雅的时钟
实现效果: 准备工作: 1# 定时器 相关知识了解 2#javascript Date(日期)对象 3# 准备效果所用图片 实现原理: 1# 获取当前时间: var time=new Date(); ...
- [RxJS] Starting a Stream with SwitchMap & switchMapTo
From an event map to another event we can use switchMap(), switchMap() accept an function which retu ...
- easyui-combobox默认值绑定
$('#combox_role').combobox({ panelHeight: , url: '../../Handler/GetComboxItems.ashx?type=0', valueFi ...
- Html与css基础
1.html的定义 (1).html:超文本标记语言(HyperText Markup Language),它主要包括"头"(Head)和"主体"(Body)两 ...
- C# Serializable学习
先上代码,感觉这个功能很给力啊. class Program { static void Main(string[] args) { //下面代码将对象Person进行序列化并存储到一个文件中 Per ...
- JS文件中加载jquery.js
原文链接:http://blog.csdn.net/whatday/article/details/39553451 最近有一个需求: 1.在一个html中只能引入一个JS文件 不能有JS代码和其他J ...
- POJ 1001 Exponentiation 模拟小数幂
模拟小数幂 小数点位 pos 非零末位 e 长度 len 只有三种情况 pos > len pos < e e < pos < len #include <iostrea ...
- Avro基础
一.Avro的基本功能 1.定义了数据模式文件的语法,一般使用json文件.以及一些数据基本类型与复杂类型. 2.定义了数据序列化到文件后的数据格式,此格式可供各种语言进行读取. 3.为部分语言定义了 ...