问题是这样出现的。

操作:client正在向服务端请求数据的时候,突然拔掉client的网线。

现象:client死等。服务端socket一直存在。

在网上搜索后,须要设置KEEPALIVE属性。

于是就在client和服务端都设置了KEEPALIVE属性。

代码例如以下:

int keepalive = 1;  // 打开keepalive

int keepidle = 10;  // 空暇10s開始发送检測包(系统默认2小时)

int keepinterval = 1;  // 发送检測包间隔 (系统默认75s)

int keepcount = 5;  // 发送次数假设5次都没有回应,就认定peer端断开了。

(系统默认9次)

setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,&keepalive, sizeof(keepalive));

setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE,&keepidle, sizeof(keepidle));

setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL,&keepinterval, sizeof(keepinterval));

setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT,&keepcount, sizeof(keepcount));

这种情况下,client没有问题了,能够主动关闭,可是服务端还是在死等。也就是说keepalive没起作用。

事实上我也没有查到原因,插一句题外话。百度搜索真是不好用(偏偏google被封了,公司也不肯买vpn,有种淡淡的忧伤)。

后来我用了一个没有被封的google ip搜索到了这样一个属性,TCP_USER_TIMEOUT (since Linux 2.6.37)。

链接:http://man7.org/linux/man-pages/man7/tcp.7.html

This option takes an unsigned int as anargument.  When the

value is greater than 0, it specifies themaximum amount of

time in milliseconds that transmitted datamay remain

unacknowledged before TCP will forciblyclose the

corresponding connection and returnETIMEDOUT to the

application.  If the option value is specified as 0, TCPwill

to use the system default.

Increasing user timeouts allows a TCPconnection to survive

extended periods without end-to-endconnectivity.  Decreasing

user timeouts allows applications to"fail fast", if so

desired. Otherwise, failure may take up to 20 minutes with

the current system defaults in a normal WANenvironment.

This option can be set during any state ofa TCP connection,

but is only effective during thesynchronized states of a

connection (ESTABLISHED, FIN-WAIT-1,FIN-WAIT-2, CLOSE-WAIT,

CLOSING, and LAST-ACK).  Moreover, when used with the TCP

keepalive (SO_KEEPALIVE) option,
TCP_USER_TIMEOUT will

overridekeepalive to determine when to close a connection due

to keepalivefailure.

The option has no effect on when TCPretransmits a packet, nor

when a keepalive probe is sent.

This option, like many others, will beinherited by the socket

returned by accept(2), if it was set on thelistening socket.

Further details on the user timeout featurecan be found in

RFC 793 and RFC 5482 ("TCP UserTimeout Option").

所以我们在服务端加上了TCP_USER_TIMEOUT属性,问题就攻克了。

unsigned int timeout = 10000;  // 10s
setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout, sizeof(timeout));

后来又搜索了一下,在以下的文章里找到了印证。

下面做一下摘录。原文请见:http://blog.leeyiw.org/tcp-keep-alive/

使用TCP KEEP-ALIVE与TCP_USER_TIMEOUT机制推断通信对端是否存活

第一个问题:

在对端的网线被拔、网卡被卸载或者禁用的时候。对端没有机会向本地操作系统发送TCP RST或者FIN包来关闭连接。

这时候操作系统不会觉得对端已经挂了。

所以在调用send函数的时候。返回的仍然是我们指定发送的数据字节数。

当我们无法通过send的返回值来推断对端是否存活的情况下。就要使用TCP Keep-alive机制了。

在《Unix网络编程(卷一)》中提到,使用SO_KEEPALIVE套接字选项启用对套接字的保活(Keep-alive)机制。

给一个TCP套接口设置保持存活(keepalive)选项后,假设在2小时内在此套接口的任一方向都没有数据交换。TCP就自己主动给对方发一个保持存活探測分节(keepalive probe)。

TCP提供了这样的机制帮我们推断对端是否存活,假设对端没有对KeepAlive包进行正常的响应,则会导致下一次对套接字的send或者recv出错。应用程序就能够检測到这个异常。

第二个问题:

假设发送方发送的数据包没有收到接收方回复的ACK数据包。则TCP Keep-alive机制就不会被启动,而TCP会启动超时重传机制。这样就使得TCP Keep-alive机制在未收到ACK包时失效。

利用keepalive和timeout来推断死连接的更多相关文章

  1. c/c++ linux epoll系列3 利用epoll_wait设置timeout时间长度

    linux epoll系列3 利用epoll_wait设置timeout时间长度 epoll_wait函数的第四个参数可以设置,epoll_wait函数的等待时间(timeout时间长度). 例子1, ...

  2. 利用keepalive+mysql replication 实现数据库的高可用

    利用keepalive+mysql replication 实现数据库的高可用 http://www.xuchanggang.cn/archives/866.html

  3. 如何利用`keep-alive`按需缓存页面数据

    随着项目不断变大,页面变多,搜索条件也随之也越来越多,而每次跳转页面再返回时,之前的筛选的条件都会别清空.之前在elment-ui table组件 -- 远程筛选排序提到过缓存,但是有所取巧,这次重新 ...

  4. HttpsURLConnection 利用keepAlive特性进行优化一例

    最近项目中,遇到一个报错: java.lang.OutOfMemoryError: unable to create new native thread 报错的场景是:一个消息的群发,群里总共有50多 ...

  5. 在c#中利用keep-alive处理socket网络异常断开的方法

    本文摘自 http://www.z6688.com/info/57987-1.htm 最近我负责一个IM项目的开发,服务端和客户端采用TCP协议连接.服务端采用C#开发,客户端采用Delphi开发.在 ...

  6. vue利用keep-alive/beforeRouteLeave前进刷新后退不刷新(缓存)

      keep-alive缓存 在vue中默认router-link进入页面组件都是不缓存的.对于数据不会更新的页面.可以使用keep-alive来缓存以提高性能. 在项目src/router/inde ...

  7. HTTP长连接--Keep-Alive

    一.HTTP/1.0 HTTP1.0版本的Keep-alive并不像HTTP1.1那样是默认发送的,所以要想连接得到保持,必须手动配置发送connection:keep-alive字段.若想断开kee ...

  8. SCRIPT7002: XMLHttpRequest: 网络错误 0x2ef3, 由于出现错误 00002ef3 而导致此项操作无法完成,浏览器中的Keep-Alive

    http://www.cnblogs.com/OpenCoder/p/5089258.html     IE中Keep-Alive机制引起的错误 我们知道Http协议是基于TCP/IP连接的,也就是说 ...

  9. 理解AngularJS生命周期:利用ng-repeat动态解析自定义directive

    ng-repeat是AngularJS中一个非常重要和有意思的directive,常见的用法之一是将某种自定义directive和ng-repeat一起使用,循环地来渲染开发者所需要的组件.比如现在有 ...

随机推荐

  1. mysql复制数据

    前言:由于工作需要,我要造大量数据,最好的方法是直接copy已有的数据,改其中一些值即可.操作的表有主键,且自增,AUTO_INCREMENT 按照以往的经验无外乎: 类别一. 如果两张张表(导出表和 ...

  2. Coursera公开课-Machine_learing:编程作业7

    这周的编程作业主要是两方面内容. 1.K-means聚类. 2.PCA(Principle Component Analys)主成分分析. 方式主要是通过对图像的聚类实现压缩图像,后来发现PCA也可以 ...

  3. 2 我们的C#学习方法

    在这里我们借鉴了一种行之有效的学习编程语言的方法,并在此基础上进行了相应的改良.我们在培训新人中使用后,发现这种学习方法是非常有效的. 你通过做以下几个步骤来一步步学习C#语言. 1. 搞懂每一个我们 ...

  4. Web程序安全机制

    ASP.NET提供了一个多层的安全模型,这个模型能够非常容易的保护Web应用程序. 安全策略没有必要非常复杂,但是需要应用安全策略的地方却是非常广泛的.程序员需要保证自己的应用程序不能被骗取,而把私有 ...

  5. Android基础TOP2:单机按钮改变字体颜色

    ---恢复内容开始--- Activity: <TextView android:id="@+id/t1" android:textSize="30dp" ...

  6. JS——百度背景图

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. 3星|《腾讯产业森林:AI时代的创业密码》:后半部分是较详细的创业指南,前面泛泛介绍腾讯、AI

    腾讯产业森林:AI时代的创业密码 前半部分泛泛介绍腾讯对创业者的支持,腾讯支持的创业项目的案例.AI的一些基本介绍,后半部分是比较详细的写给创业者的各阶段行动与选择的指南. 总体评价3星,有一些参考价 ...

  8. nagios插件nagiosql安装配置

    nagios插件nagiosql安装配置 # Nagiosql install [root@Cagios ~]# yum install -y libssh2 libssh-devel [root@C ...

  9. Cesium学习笔记(四)Camera ----http://blog.csdn.net/hobhunter/article/details/74909641

    Cesium 相机控制场景中的视野.操作相机的方法有很多,如旋转,缩放,平移和飞到目的地.Cesium具有默认的鼠标和触摸事件处理程序与相机进行交互,还有一个API以编程方式操纵相机. 我们可以使用该 ...

  10. 10.3 io流 正篇 FileReader FileWriter读写代码

    一.FileWriter 小节: 1)FileWriter fw = new FileWriter("a.txt",true);//表示追加写入,默认是false.正常情况:执行多 ...