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的机理及使用的更多相关文章

  1. TCP keepalive overview

    2. TCP keepalive overview In order to understand what TCP keepalive (which we will just call keepali ...

  2. 【转载】TCP保活(TCP keepalive)

    下图是我遇到tcp keepalive的例子: 以下为转载: TCP保活的缘起 双方建立交互的连接,但是并不是一直存在数据交互,有些连接会在数据交互完毕后,主动释放连接,而有些不会,那么在长时间无数据 ...

  3. TCP keepalive under Linux

    TCP Keepalive HOWTO Prev   Next 3. Using TCP keepalive under Linux Linux has built-in support for ke ...

  4. TCP keepalive

      2. TCP keepalive overview In order to understand what TCP keepalive (which we will just call keepa ...

  5. TCP连接探测中的Keepalive和心跳包. 关键字: tcp keepalive, 心跳, 保活

    1. TCP保活的必要性 1) 很多防火墙等对于空闲socket自动关闭 2) 对于非正常断开, 服务器并不能检测到. 为了回收资源, 必须提供一种检测机制. 2. 导致TCP断连的因素 如果网络正常 ...

  6. TCP Keepalive HOWTO

    TCP Keepalive HOWTO Fabio Busatto <fabio.busatto@sikurezza.org> 2007-05-04 Revision History Re ...

  7. 【 总结 】Tcp Keepalive 和 HTTP Keepalive 详解

    TCP Keepalive Tcp keepalive的起源          双方建立交互的连接,但是并不是一直存在数据交互,有些连接会在数据交互完毕后,主动释放连接,而有些不会,那么在长时间无数据 ...

  8. tcp keepalive选项

    之前一直对tcp keepalive选项理解有误, 以为通过setsockopt函数设置SO_KEEPALIVE和相关参数后该socket则使用设置的keepalive相关参数 否则使用系统默认的:k ...

  9. TCP长连接保持连接状态TCP keepalive设置

    如有转载,请注明出处:http://blog.csdn.net/embedded_sky/article/details/42077321 作者:super_bert@csdn 对于TCP长连接保活是 ...

随机推荐

  1. Leetcode938. Range Sum of BST二叉搜索树的范围和

    给定二叉搜索树的根结点 root,返回 L 和 R(含)之间的所有结点的值的和. 二叉搜索树保证具有唯一的值. 示例 1: 输入:root = [10,5,15,3,7,null,18], L = 7 ...

  2. fstream文件打开模式

    fstream:对于文件的操作很久两年前就开始使用了,但是仅仅为了达到满足自己需求的目的,就是要么是写,要么是读.从来没有对其进行详细的了解.自己也曾经想过花一点时间去总结一下,这个东西到底应该怎么用 ...

  3. Apache 禁用IP 访问 和 HTTP 跳转 HTTPS

    如果需要 禁用IP 访问并且 需要 HTTP 跳转到 HTTPS <VirtualHost *:80> ServerName xxx.xxx.com RewriteEngine On Re ...

  4. HZOI2019序列

    题目链接:https://www.cnblogs.com/Juve/articles/11186805.html(密码是我的一个oj用户名) 题解: 这题我考试打的暴力,只有5分. 一开始理解错题意了 ...

  5. Beyond Compare注册码

    注册码: --- BEGIN LICENSE KEY --- H1bJTd2SauPv5Garuaq0Ig43uqq5NJOEw94wxdZTpU-pFB9GmyPk677gJ vC1Ro6sbAvK ...

  6. 微信小程序--导航跟随

    最近开发小程序的时候遇到这样一个需求:如图1 页面向下滚动到白色导航的位置时,白色导航固定到页面最上方:当页面向上滚动到白色导航时,白色导航恢复到原始位置:点击各个导航,平滑的跳到相应位置. 思路1: ...

  7. 软件-MQ-MQ:IBM MQ

    ylbtech-软件-MQ-MQ:MQ(IBM MQ) MQ传递主干,在世界屡获殊荣. 它帮您搭建企业服务总线(ESB)的基础传输层.IBM WebSphere MQ为SOA提供可靠的消息传递.它为经 ...

  8. Python导出DBF文件到Excel的方法

    Python导出DBF文件到Excel的方法 这篇文章主要介绍了Python导出DBF文件到Excel的方法,实例分析了Python基于win32com模块实现文件导出与转换的相关技巧,分享给大家供大 ...

  9. Mysql中ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8怎么转换为sql sever2008的代码

    ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8转换sql server AUTO_INCREMENT=2 ,是 自动递增列的 初始数值 = 2, ...

  10. 几个树形dp

    1.重建道路 树形dp基础题,f[i][j]表示在i这个点我和我的子树联通块大小为j最少砍几条边. 转移的时候,到下一个子树时上一个子树所有答案先++(此树直接砍掉不贡献答案),再继续dp. 注意更新 ...