目前手头有个关于心博功能的一个案例, 在使用SOL_SOCKET, SO_KEEPALIVE上有一点心得,想写出来和大家分享一下。

关于SOL_SOCKET选项SO_KEEPALIVE有一个很详细的英文How TO, 在下面的网页中大家可以看到详细的内容
http://www.icewalkers.com/Linux/Howto/TCP-Keepalive-HOWTO/index.html

在《UNIX网络编程第1卷》中也有详细的阐述:

SO_KEEPALIVE 保持连接检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP连接的输入。设置该选项后,如果2小时内在此套接口的任一方向都没有数据交换,TCP就自动给对方 发一个保持存活探测分节(keepalive probe)。这是一个对方必须响应的TCP分节.它会导致以下三种情况:对方接收一切正常:以期望的ACK响应。2小时后,TCP将发出另一个探测分节。对方已崩溃且已重新启动:以RST响应。套接口的待处理错误被置为ECONNRESET,套接 口本身则被关闭。对方无任何响应:源自berkeley的TCP发送另外8个探测分节,相隔75秒一个,试图得到一个响应。在发出第一个探测分节11分钟15秒后若仍无响应就放弃。套接口的待处理错误被置为ETIMEOUT,套接口本身则被关闭。如ICMP错误是“host unreachable(主机不可达)”,说明对方主机并没有崩溃,但是不可达,这种情况下待处理错误被置为 EHOSTUNREACH。

在该书的第158页有更详细的描述。

根据上面的介绍我们可以知道对端以一种非优雅的方式断开连接的时候,我们可以设置SO_KEEPALIVE属性使得我们在2小时以后发现对方的TCP连接是否依然存在。

keepAlive = 1;
Setsockopt(listenfd, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(keepAlive));

如果我们不能接受如此之长的等待时间,从TCP-Keepalive-HOWTO上可以知道一共有两种方式可以设置,一种是修改内核关于网络方面的配置参数,另外一种就是SOL_TCP字段的TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT三个选项。

The tcp_keepidle parameter specifies the interval of inactivity that causes TCP to generate a KEEPALIVE transmission for an application that requests them. tcp_keepidle defaults to 14400 (two hours).

/*开始首次KeepAlive探测前的TCP空闭时间 */

The tcp_keepintvl parameter specifies the interval between the nine retries that are attempted if a KEEPALIVE transmission is not acknowledged. tcp_keepintvl defaults to 150 (75 seconds).
/* 两次KeepAlive探测间的时间间隔  */

The TCP_KEEPCNT option specifies the maximum number of keepalive probes to be sent. The value of TCP_KEEPCNT is an integer value between 1 and n, where n is the value of the systemwide tcp_keepcnt parameter.

/* 判定断开前的KeepAlive探测次数 */

因此我们可以得到
    int                 keepIdle = 6;
    int                 keepInterval = 5;
    int                 keepCount = 3;

Setsockopt(listenfd, SOL_TCP, TCP_KEEPIDLE, (void *)&keepIdle, sizeof(keepIdle));

Setsockopt(listenfd, SOL_TCP,TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));

Setsockopt(listenfd,SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));

我们需要注意的TCP-Keepalive-HOWTO上这段话:

Remember that keepalive is not program−related, but socket−related, so if you have multiple sockets, you can handle keepalive for each of them separately.

这些属性是sockt继承的,非整个代码内的所有sockets都继承这个属性,因为如果要应用到多个套接口上必须分别使用Setsockopt, Setsockopt是setsockopt的包裹函数。

如果心搏函数要维护客户端的存活,即服务器必须每隔一段时间必须向客户段发送一定的数据,那么使用SO_KEEPALIVE是有很大的不足的。因为SO_KEEPALIVE选项指"此套接口的任一方向都没有数据交换",我不知道大家是怎么理解这个实现的。在Linux 2.6系列上,上面话的理解是只要打开SO_KEEPALIVE选项的套接口端检测到数据发送或者数据接受就认为是数据交换。

因此在这种情况下使用 SO_KEEPALIVE选项 检测对方是否非正常连接是完全没有作用的,在每隔一段时间发包的情况, keep-alive的包是不可能被发送的。上层程序在非正常端开的情况下是可以正常发送包到缓冲区的。非正常端开的情况是指服务器没有收到"FIN" 或者 "RST"包。

当然这种情况也是比较好断定对方是否存活,我提出来的主要原因是想看看大家对"此套接口的任一方向都没有数据交换"是怎么去理解的。

SO_KEEPALIVE相关推荐

  1. 【Netty】option(ChannelOption.SO_KEEPALIVE, true) socket参数详解:KeepAlive

    .childOption(ChannelOption.SO_KEEPALIVE, true); childOption是用来给父级ServerChannel之下的Channels设置参数的 当设置为t ...

  2. linux socket SO_KEEPALIVE选项

    连接关闭的两种情况 对于面向连接的TCP socket,在实际应用中通常都要检测对端是否处于连接中,连接端口分两种情况: 1.连接正常关闭,调用close() shutdown()连接优雅关闭,sen ...

  3. 套接字选项SO_KEEPALIVE

    套接字选项SO_KEEPALIVE是保活套接字,它会在规定的时间内给对端发送探测分节,用tcpdump抓包可以看到.这个规定的时间就是net.ipv4.tcp_keepalive_time,在系统中可 ...

  4. java socket 如何设置so_keepalive属性_socket通信的KeepAlive设定

    socket通信的KeepAlive默认时间是2小时,通过以下代码可以改变其时间,来检测socket通信过程中自网线,服务器网线断等事件 #include #include "winsock ...

  5. Linux下高性能网络编程中的几个TCP/IP选项_SO_REUSEADDR、SO_RECVBUF、SO_SNDBUF、SO_KEEPALIVE、SO_LINGER、TCP_CORK、TCP_NODE

    最近在新的平台上测试程序,以前一些没有注意到的问题都成为了性能瓶颈,通过设置一些TCP/IP选项能够解决一部分问题,当然根本的解决方法是重构代码,重新设计服务器框架.先列出几个TCP/IP选项: 选项 ...

  6. Linux SO_KEEPALIVE属性,心跳

    对于面向连接的TCP socket,在实际应用中通常都要检测对端是否处于连接中,连接端口分两种情况: 1.连接正常关闭,调用close() shutdown()连接优雅关闭,send与recv立马返回 ...

  7. 继续研究 SO_KEEPALIVE 问题

    借助于网上他人文章,研究 SO_KEEPLIVE 问题:http://www.iteye.com/topic/1118643 client端加了 setsockopt 函数调用.看看能否在服务器端未启 ...

  8. linux so keepalive,Linux SO_KEEPALIVE

    对于面向连接的TCP socket,在实际应用中通常都要检测对端是否处于连接中,连接端口分两种情况: 1.连接正常关闭,调用close() shutdown()连接优雅关闭,send与recv立马返回 ...

  9. 轻量级分布式 RPC 框架

    RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样. RPC 可基于 HTTP 或 TCP 协议,Web Servi ...

最新文章

  1. 基于Laravel开发博客应用系列 —— 构建博客后台管理系统
  2. 抽象类可以生成自己的对象吗_大理石可以自己抛光吗?大理石自己抛光方法解答...
  3. 建议重写equals方法时也一并重写hashCode方法
  4. 通过数据评估渠道用户质量的方法
  5. Oracle云安全服务半年收获100万用户
  6. 写给《我也能做CTO》作者的一封信
  7. 昆仑通态复制的程序可以用吗_昆仑通态专题(九):MCGS组态软件的实时数据库...
  8. OpenCV阈值分割
  9. 金蝶K3 数据表知识整理(不断完善)
  10. 时间序列分析(一) 如何判断序列是否平稳
  11. Builder中使用Access数据库
  12. 聊聊苹果电脑上不错的三维建模软件
  13. 通达OA2019安装教程
  14. word域转换html,word域代码转换html丢失解决办法.docx
  15. 有关键词和频率,怎么求共词矩阵?有报酬
  16. iterator的用法及概念
  17. 99_包(package)
  18. 超便捷好用的-圆形花瓣加载滚动图片插件spin.js
  19. FlexRay汽车通信总线介绍及测试环境
  20. 免费是王道!盘点国外十款免费好用的反病毒软件产品

热门文章

  1. 网站底部的统计代码HTML
  2. 自动驾驶辅助系统性能评估工具MXeval4.1版本更新快讯
  3. CentOS opera 浏览器
  4. radius认证服务
  5. python根据IP判断地理位置
  6. Access update语句 提示 操作必须使用一个可更新的查询Access update语句 提示 操作必须使用一个可更新的查询
  7. '操作必须使用一个可更新的查询'解决方法
  8. Flow公链 |动态交易手续费
  9. es根据字段长度过滤_ES Aggs根据聚合的结果(数值)进行过滤
  10. 1加到100用python实现