/* 设置套接字选项周期性消息检测连通性 心跳包、 心博。主要用于长连接。
* 参数:套接字, 1或0开启, 首次间隔时间, 两次间隔时间, 断开次数
*/
void setKeepAlive( int iSockfd , int iSockAttrOn, socklen_t iIdleTime , socklen_t iInterval , socklen_t iCount ){
setsockopt( iSockfd , SOL_SOCKET , SO_KEEPALIVE , (const char*)&iSockAttrOn , sizeof(iSockAttrOn) );
setsockopt( iSockfd , SOL_TCP , TCP_KEEPIDLE , (const char*)&iIdleTime , sizeof(iIdleTime) );
setsockopt( iSockfd , SOL_TCP , TCP_KEEPINTVL , (const char*)&iInterval,sizeof(iInterval) );
setsockopt( iSockfd , SOL_TCP , TCP_KEEPCNT , (const char*)&iCount,sizeof(iCount) );
}
/* 绑定地址复用. 主要用于TCP Server端 */
setsockopt(iSockfd, SOL_SOCKET, SO_REUSEADDR, &iSockAttrOn,sizeof(iSockAttrOn) );

SO_KEEPALIVE 保持连接检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP连接的输入。设置该选项后,如果2小时内在此套接口的任一方向都没有数据交换(即服务器没有发送数据或者接收数据),TCP就自动给对方发一个保持存活探测分节(keepalive probe)。这是一个对方必须响应的TCP分节.它会导致以下三种情况:

  • 对方接收一切正常:以期望的ACK响应。
  • 2小时后,TCP将发出另一个探测分节。对方已崩溃且已重新启动:以RST响应。套接口的待处理错误被置为ECONNRESET(recv返回0,errno为ECONNRESET),套接字本身则被关闭。
  • 对方无任何响应:源自berkeley的TCP发送另外8个探测分节,相隔75秒一个,试图得到一个响应。在发出第一个探测分节11分钟15秒(9*75s)后若仍无响应就放弃。套接口的待处理错误被置为ETIMEOUT,套接口本身则被关闭。如ICMP错误是“host unreachable(主机不可达)”,说明对方主机并没有崩溃,但是不可达,这种情况下待处理错误被置为EHOSTUNREACH。

如果我们不能接受如此之长的等待时间,从TCP-Keepalive-HOWTO上可以知道一共有两种方式可以设置。

  • 修改内核关于网络方面的配置参数
echo 30 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 10 > /proc/sys/net/ipv4/tcp_keepalive_intvl
echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes

  • SOL_TCP字段的TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT三个选项

1) 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空闭时间 */

2) 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探测间的时间间隔  */

3) 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 = 1000;
int keepInterval = 10;
int keepCount = 10;
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));

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.

我们需要注意的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继承的,即listen的套接字设置该属性后,后面建立连接后的accept 套接字同样继承该属性(心跳属性)。

如果心搏函数要维护客户端的存活,即服务器必须每隔一段时间必须向客户段发送一定的数据,那么使用SO_KEEPALIVE是有很大的不足的。因为SO_KEEPALIVE选项指"此套接口的任一方向都没有数据交换"。在Linux 2.6系列上,上面话的理解是只要打开SO_KEEPALIVE选项的套接口端检测到数据发送或者数据接收就认为是数据交换。即在非正常断开的情况下(服务器没有收到“FIN”或者“RST”包),上层程序还是可以正常发送包到缓冲区的,而客户端已经异常断开,导致TCP会自动进行重传,重传包的优先级高于keepalive包,那就意味着keepalive总是不能发送出去,这时我们并不知道该连接已经出错而中断,在较长时间的重传失败之后,再发keepalive之后我们才知道客户端异常退出。

阅读此博客时,可以参考后面的博客<<UNIX网络编程——客户/服务器心搏函数>>和<<UNIX网络编程——socket的keep-alive>>。

UNIX网络编程——套接字选项(心跳检测、绑定地址复用)的更多相关文章

  1. UNIX网络编程——套接字选项(SOL_SOCKET级别)

    #include <sys/socket.h> int setsockopt( int socket, int level, int option_name,const void *opt ...

  2. UNIX网络编程——套接字选项

    http://www.educity.cn/linux/1241288.html 有时候我们需要控制套接字的行为(如修改缓冲区的大小),这个时候我们就要学习套接字选项. int getsockopt( ...

  3. UNIX网络编程——套接字选项(SO_REUSEADDR)

    1.一般来说,一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR是让端口释放后立即就可以被再次使用. SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的sock ...

  4. UNIX网络编程——套接字选项(SO_RCVBUF和SO_SNDBUF)

    有时候我们需要控制套接字的行为(如修改缓冲区的大小),这个时候我们就要学习套接字选项. int getsockopt(int sockfd,int level,int optname,void *op ...

  5. UNIX网络编程——套接字选项(setsockopt)

    setsockopt的一些用法: close socket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket: BOOL bReuseaddr=TRUE; setsockop ...

  6. unix网络编程-套接字编程 读书笔记

    1. 学习总结(目前只看了前6章):http://note.youdao.com/noteshare?id=2a0c29f5feeddd8f6f390427f0d67114 2. 课后习题 第一章 h ...

  7. 网络编程 套接字socket TCP UDP

    网络编程与套接字 网络编程 网络编程是什么: ​ 网络通常指的是计算机中的互联网,是由多台计算机通过网线或其他媒介相互链接组成的 ​ 编写基于网络的应用程序的过程序称之为网络编程. 网络编程最主要的工 ...

  8. <网络编程>套接字介绍

    1.端口:IANA(Internet Assigned Numbers Authority)维护着一个端口号分配状况的清单. 众所周知的端口(0-1023):由IANA分配和控制,可能的话,相同的端口 ...

  9. Java网络编程--套接字Socket

    一.套接字Socket IP地址标志Internet上的计算机,端口号标志正在计算机上运行的进程(程序). 端口号被规定为一个16位的0--65535之间的整数,其中,0--1023被预先定义的服务通 ...

随机推荐

  1. Spring MVC - 静态页面

    环境搭建 以下示例显示如何使用Spring MVC Framework编写一个简单的基于Web的应用程序,它可以使用<mvc:resources>标记访问静态页面和动态页面.首先使用Int ...

  2. java表达式类型的自动提升

    当一个java算术表达式中包含多个基本类型的值时,整个算术表达式的数据类型将发生自动提升.Java定义如下的自动提升规则:1. 所有byte型.short型和char型将被提升到int型. 2. 整个 ...

  3. linux上快速搭建宝塔面板来操作便捷功能

    关于宝塔 Linux版请确保纯净系统安装(支持CentOS.Ubuntu.Debian.Fedora.Deepin),Web端管理,QQ群及论坛技术支持一键LAMP/LNMP.创建网站FTP.数据库. ...

  4. Python中的str与unicode处理方法

    Python中的str与unicode处理方法 2015/03/25 · 基础知识 · 3 评论· Python 分享到:42 原文出处: liuaiqi627 的博客    python2.x中处理 ...

  5. 字符流之FileReader&FileWriter

    package zhang; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; pub ...

  6. Jmeter(二十)_Mock接口

    首先解释一下什么是mock接口. Mock通常是指,在测试一个对象时,我们构造一些假的对象来模拟与其交互.而这些Mock对象的行为是我们事先设定且符合预期.通过这些Mock对象来测试对象在正常逻辑,异 ...

  7. Docker环境 ELK 快速部署

    Docker环境 ELK快速部署 环境 Centos 7.4 , Docker version 17.12 Docker至少3GB内存: #内核配置 echo ' vm.max_map_count = ...

  8. 深入Java虚拟机(1)——Java体系结构

    Java体系结构 Java体系结构包括四个独立但相关的技术: 1.Java程序设计语言 2.Java class文件格式 3.Java应用编程接口(API) 4.Java虚拟机 当编写并运行一个Jav ...

  9. Swift中方法闭包参数不能省略括号的一种情况

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 我们知道在swift中,如果方法的最后一个参数是一个闭包类型, ...

  10. 漏洞挖局利器-Fuzz技术介绍

    模糊测试的定义 模糊测试定义为"通过向应用提供非预期的输入并监控输出中的异常来发现软件中的故障(faults)的方法". 典型而言,模糊测试利用自动化或是半自动化的方法重复地向应用 ...