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长连接保活是 ...
随机推荐
- ubuntu 安装samba共享文件夹
安装samba sudo apt-get install samba smbclient 配置samba sudo cp /etc/samba/smb.conf /etc/samba/smb.conf ...
- [转]8天玩转并行开发——第二天 Task的使用
在我们了解Task之前,如果我们要使用多核的功能可能就会自己来开线程,然而这种线程模型在.net 4.0之后被一种称为基于 “任务的编程模型”所冲击,因为task会比thread具有更小的性能开销,不 ...
- php 支付宝新版本app支付以及回调
;支付宝快速接入; 支付宝2017年新版本支付基本业务逻辑 服务端生成字符串 交给客户端, 客户端调用接口,将这段字符串str传过去 调用起支付界面. 其中字符串str包含了所有请求参数,以及请求参数 ...
- Python pylint的安装和使用
Pylint 是一个 Python 代码分析工具,它分析 Python 代码中的错误,查找不符合代码风格标准和有潜在问题的代码. Pylint 是一个 Python 工具,除了平常代码分析工具的作用之 ...
- $cordovaNetwork 使用
1 .安装插件 直接安装: cordova plugin add cordova-plugin-network-information 下载到本地安装: https://github.com/apac ...
- vim中利用swp文件进行恢复
经常电脑因为没电或者强行关闭vim,会导致原文件没有保存, 这种情况下vim会自动保存一个.swp文件,需要恢复时, 使用vim -r filename 期中-r意思为recovery 恢复之后最好删 ...
- 约束布局ConstraintLayout加快布局速度
Android Studio2.2更新布局设计器,同时,引人了约束布局ConstraintLayout. 简单来说,可以把它看做是相对布局的升级版本,但是区别与相对布局更加强调约束.何为约束,即控件之 ...
- MySQL时间格式转换
1.时间转换成特定字符串 例:select DATE_FORMAT(now(),'%Y-%m-%d %H:%i::%s'); --> '2019-10-16 10:59::18' 2.一种字符串 ...
- String、StringBuffer和StringBuilder源码解析
1.String 1.1类的定义 public final class String implements java.io.Serializable, Comparable<String> ...
- LOJ 6042 跳蚤王国的宰相
LOJ 6042 跳蚤王国的宰相 题意 跳蚤王国爆发了一场动乱,国王在镇压动乱的同时,需要在跳蚤国地方钦定一个人来做宰相. 由于当时形势的复杂性,很多跳蚤都并不想去做一个傀儡宰相,带着宰相的帽子,最后 ...