TCP keepalive的机理及使用
TCP 是面向连接的 , 在实际应用中通常都需要检测对端是否还处于连接中。如果已断开连接,主要分为以下几种情况:
1.连接的对端正常关闭,即使用 closesocket 关闭连接。
2.连接的对端非正常关闭,包括对端异常关闭,网络断开等情况。
对于第一种情况,很好判断,但是对于第二种情况,可能会要麻烦一些。在网上找到了一些文章,大致有以下两种解决方法:
自己编写心跳包程序
简单的说也就是在自己的程序中加入一条线程,定时向对端发送数据包,查看是否有 ACK ,如果有则连接正常,没有的话则连接断开。
使用 TCP 的 keepalive 机制
这个需要在 WinSock 编程时对当前 SOCKET 进行相应设置即可,比较方便。
为了方便起见,我这里采用 keepalive 机制,下面我就以 WinSock 上我实验得到的结果来大致讲一下其机理和使用方法。
首先说一下 keepalive 来判断异常断开的原理,其实 keepalive 的原理就是 TCP 内嵌的一个心跳包。
以服务器端为例,如果当前 server 端检测到超过一定时间(默认是 7,200,000 milliseconds ,也就是 2 个小时)没有数据传输,那么会 向client 端发送一个 keep-alive packet (该 keep-alive packet 就是 ACK 和当前 TCP 序列号减一的组合),此时 client 端应该为以下三种情况之一:
1. client 端仍然存在,网络连接状况良好。此时 client 端会返回一个 ACK 。 server 端接收到 ACK 后重置计时器,在2 小时后再发送探测。如果 2 小时内连接上有数据传输,那么在该时间基础上向后推延 2 个小时。
2. 客户端异常关闭,或是网络断开。在这两种情况下, client 端都不会响应。服务器没有收到对其发出探测的响应,并且在一定时间(系统默认为 1000 ms )后重复发送 keep-alive packet ,并且重复发送一定次数( 2000 XP 2003 系统默认为 5 次 , Vista 后的系统默认为 10 次)。
3. 客户端曾经崩溃,但已经重启。这种情况下,服务器将会收到对其存活探测的响应,但该响应是一个复位,从而引起服务器对连接的终止。
测试代码如下:
- #ifdef WIN32
- //#include <WS2tcpip.h>
- #include <mstcpip.h>
- #else
- #include <netinet/in.h>
- #include <netinet/tcp.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #endif
- void WanLanTcpClient::setKeepalive(int sock, int keepAlive, int keepInterval, int keepCount, int keepIdle)
- {
- #ifdef WIN32
- BOOL bKeepAlive = TRUE;
- int nRet = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
- (char*)&bKeepAlive, sizeof(bKeepAlive));
- if (nRet == SOCKET_ERROR)
- {
- ERROR_LOG("setsockopt failed: %d", WSAGetLastError());
- return;
- }
- // set KeepAlive parameter
- tcp_keepalive alive_in;
- tcp_keepalive alive_out;
- alive_in.keepalivetime = keepAlive; //3000ms
- alive_in.keepaliveinterval = keepInterval; //300ms
- alive_in.onoff = TRUE;
- unsigned long ulBytesReturn = ;
- nRet = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &alive_in, sizeof(alive_in),
- &alive_out, sizeof(alive_out), &ulBytesReturn, NULL, NULL);
- if (nRet == SOCKET_ERROR)
- {
- ERROR_LOG("WSAIoctl failed: %d/n", WSAGetLastError());
- return;
- }
- #else
- //keepAlive = 1; //开启keepalive属性. 缺省值: 0(关闭)
- keepIdle = ; //如果在1秒内没有任何数据交互,则进行探测. 缺省值:7200(s)
- keepInterval = ; //探测时发探测包的时间间隔为1秒. 缺省值:75(s)
- keepCount = ; //探测重试的次数. 全部超时则认定连接失效..缺省值:9(次)
- setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(keepAlive));
- setsockopt(sock, IPPROTO_TCP, TCP_KEEPALIVE, (void*)&keepIdle, sizeof(keepIdle));
- setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, (void*)&keepInterval, sizeof(keepInterval));
- setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, (void*)&keepCount, sizeof(keepCount));
- #endif
- }
TCP keepalive的机理及使用的更多相关文章
- TCP keepalive overview
2. TCP keepalive overview In order to understand what TCP keepalive (which we will just call keepali ...
- 【转载】TCP保活(TCP keepalive)
下图是我遇到tcp keepalive的例子: 以下为转载: TCP保活的缘起 双方建立交互的连接,但是并不是一直存在数据交互,有些连接会在数据交互完毕后,主动释放连接,而有些不会,那么在长时间无数据 ...
- TCP keepalive under Linux
TCP Keepalive HOWTO Prev Next 3. Using TCP keepalive under Linux Linux has built-in support for ke ...
- TCP keepalive
2. TCP keepalive overview In order to understand what TCP keepalive (which we will just call keepa ...
- TCP连接探测中的Keepalive和心跳包. 关键字: tcp keepalive, 心跳, 保活
1. TCP保活的必要性 1) 很多防火墙等对于空闲socket自动关闭 2) 对于非正常断开, 服务器并不能检测到. 为了回收资源, 必须提供一种检测机制. 2. 导致TCP断连的因素 如果网络正常 ...
- TCP Keepalive HOWTO
TCP Keepalive HOWTO Fabio Busatto <fabio.busatto@sikurezza.org> 2007-05-04 Revision History Re ...
- 【 总结 】Tcp Keepalive 和 HTTP Keepalive 详解
TCP Keepalive Tcp keepalive的起源 双方建立交互的连接,但是并不是一直存在数据交互,有些连接会在数据交互完毕后,主动释放连接,而有些不会,那么在长时间无数据 ...
- tcp keepalive选项
之前一直对tcp keepalive选项理解有误, 以为通过setsockopt函数设置SO_KEEPALIVE和相关参数后该socket则使用设置的keepalive相关参数 否则使用系统默认的:k ...
- TCP长连接保持连接状态TCP keepalive设置
如有转载,请注明出处:http://blog.csdn.net/embedded_sky/article/details/42077321 作者:super_bert@csdn 对于TCP长连接保活是 ...
随机推荐
- transform函数
C++学习[原创]transform函数的应用 transform(first,last,result,op);//first是容器的首迭代器,last为容器的末迭代器,result为存放结果的容器, ...
- 页面跳转不带 referrer的方法
如果页面中包含了如下 meta 标签,所有从当前页面中发起的请求将不会携带 referer: <meta name="referrer" content="neve ...
- IIS+PHP+MYSQL搭建
以下安装过程是在win7环境下: mysql安装参照前面windows下的mysql zip格式安装.下面主要讲除mysql以外的安装. 一.IIS安装 确保CGI被安装. 二.IIs安装成功后,安装 ...
- light oj 1071 dp(吃金币升级版)
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> ...
- git commit规范工具
npm install -g commitizen commitizen init cz-conventional-changelog --save --save-exact 以后,凡是用到git c ...
- 约束布局ConstraintLayout加快布局速度
Android Studio2.2更新布局设计器,同时,引人了约束布局ConstraintLayout. 简单来说,可以把它看做是相对布局的升级版本,但是区别与相对布局更加强调约束.何为约束,即控件之 ...
- Java虚拟机系列(五)---垃圾收集(GC)
Java语言最大的优势除了它的平台无关性之外,还有它的自动内存分配和垃圾收集技术,本节我先来总结一下垃圾收集相关的内容.本文将从解答以下三个问题的角度来展开: 1.哪些内存需要回收? 2.什么时候回收 ...
- 通过Angular-cli创建新项目
前提:已经安装Git 方法一:(推荐) 1.在需要创建项目的文件夹中右键打开 Git Bush Here ,在此输入 ng new ‘项目名’ --skip-install (如下my-app ...
- String和StringBuffer的区别;字符串的一些基本方法
String 和 StringBuffer区别 字符串广泛应用 在Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串. 需要注意的是,String的 ...
- Ajax和json一道基本的练习题
关于ajax是javaEE中最基本的操作: 下面是这道题: 基本功能: jsp+servlet+ajax实现用户信息查询,实现无刷新删除 用户信息包括 学号 姓名 出生日期 性别 操作 2017010 ...