【转】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来解决的。

时间: 2024-10-26 10:05:07

【转】Linux下socket keep alive讲解的相关文章

linux下socket keep alive讲解

[需求] 不影响服务器处理的前提下,检测客户端程序是否被强制终了.[现状]服务器端和客户端的Socket都设定了keepalive属性.服务器端设定了探测次数等参数,客户端.服务器只是打开了keepalive机能服务器端起了一个监视线程,利用select来检测socket是否被关闭... 下面这是我的一点肤浅理解. 1.关于keep alive 无论windows,还是linux,keepalive就三个参数: sk->keepalive_probes:探测次数sk->keepalive_ti

Linux下socket编程基本知识

本文档主要讲解了Linux下socket编程的一些基本知识,主要包括套接字和字节序的概念,以及一些常用的结构体和函数. 本文是在网易云课堂学习过程中的记录,这个老师讲得很不错,推荐大家围观. Linux网络编程 Linux网络编程|人工智能物联网 1.概念 1.1套接字(socket) Socket(套接字)是一种通讯机制,它包含一整套的调用接口和数据结构的定义,它给应用进程提供了使用如TCP/UDP等网络协议进行网络通讯的手段. Linux中的网络编程通过socket接口实现,socket既是

Linux下Socket编程

http://blog.chinaunix.net/uid-20733992-id-3450058.html 原文地址:Linux下Socket编程 作者:yulianliu1218 Linux下Socket编程 什么是Socket Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序.要学Internet上的TCP/IP网络编程,必须理解Socket接口. Socket接口设计者最先是将接口放在Unix操作系统里面

Linux下Socket编程的端口问题( Bind error: Address already in use )

Linux下Socket编程的端口问题( Bind error: Address already in use ) 在进行linux网络编程时,每次修改了源代码并再次编译运行时,常遇到下面的地使用错误: Bind error: Address already in use 虽然用Ctrl+C强制结束了进程,但错误依然存在,用netstat -an |grep 5120和ps aux |grep 5120都还能看到刚才用Ctrl+C“强制结束”了的进程,端口还是使用中,只好每次用kill结束进程,

Linux下socket编程,附带tcp例子

1.网络中进程之间如何通信? 本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用(Solaris门和Sun RPC) 但这些都不是本文的主题!我们要讨论的是网络中进程之间如何通信?首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的.其实TCP/IP协议族已经帮我们解决了这个问

linux下socket调试

在调试pcie板卡驱动的过程中由于要搭建测试环境,在web前端与pcie板卡之间采用socket进行通信.要测试的就是linux系统的pc机能发送一个文件给pcie板卡,然后再接收到pcie板卡处理后的文件. 工程是之前的同事留下的,没有交接.调试过程及出现的问题如下所述: (1)编译pcie驱动源码. (2)加载该驱动模块. (3)编译服务(测试环境)源码,包含socket server. (4)运行服务,运行了socket server. 该服务已经被添加到系统中,linux下查看服务的命令

Linux下socket编程(转载自http://blog.csdn.net/hguisu/article/details/7445768/)

Linux的SOCKET编程详解 1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系统为进程通信提供了相应设施,如 UNIX BSD有:管道(pipe).命名管道(named pipe)软中断信号(signal) UNIX system V有:消息(message).共享存储区(shared memory)和信号量(semaphore)等. 他们都仅限于用在本机进程之间通信.网间进

linux下socket connect阻塞方式 阻塞时间控制

同事今天问我,如何在linux下的c代码里面控制connect的阻塞时间.应用的背景是:linux下的c程序有两个目标IP需要connect,如果用阻塞方式,当其中一个IP不能连接的情况下,程序将阻塞在connect函数上.本来以为用setsockopt修改个什么参数就可以搞定,结果baidu了半天也没有结果.倒是在网上搜到很多这样的解决方案:将connect方式设置为非阻塞方式,这样程序一旦执行就会马上返回,但问题是,到底有没有连接上呢,你需要等待一段时间,然后使用函数判断连接是否正常.试了下

Linux下sudo命令实例讲解

一.sudo简介 1.概念: sudo是linux下常用的允许普通用户使用超级用户权限的工具,允许系统管理员让普通用户执行一些或者全部的root命令,如halt,reboot,su等等.这样不仅减少了root用户的登陆和管理时间,同样也提高了安全性.Sudo不是对shell的一个代替,它是面向每个命令的. 它的特性主要有这样几点: 1.sudo能够限制用户只在某台主机上运行某些命令. 2.sudo提供了丰富的日志,详细地记录了每个用户干了什么.它能够将日志传到中心主机或者日志服务器. 3.sud