socket选项自带的TCP异常断开检测

TCP异常断开是指在突然断电,直接拔网线等等情况下,如果通信双方没有进行数据发送通信等处理的时候,无法获知连接已经断开的情况.

  在通常的情况下,为了使得socket通信不受操作系统的限制,需要自己在应用层实现心跳包机制,来检查异常断开的情况,一般的方式就是服务器在一段时间没有收到客户端数据包时,定时发包,然后客户端回应,如果已经出现异常断开则服务器接收会返回错误,而客户端在指定时间内没有收到数据包,则主动向服务器发包,得到错误就说明断开.诸如此类的方式就是自己实现的心跳包机制.

  但操作系统本身也自带了一些心跳包机制,这些机制是由socket的TCP栈底层实现的,不会影响应用层通信,也不需要应用层自己处理,发现异常断开可以自行检查出来并返回错误(它的本质也是在空闲时发送心跳包).以下介绍一下Windows以及linux下的方法.

  首先介绍Windows下的方法,该方式要求通信双方必须都是Windows NT以上操作系统(如果是其它版本操作系统,如linux等等,不敢保证100%无效).MSDN中有描述WSAIoctl中的SIO_KEEPALIVE_VALS选项,该选项以及struct tcp_keepalive的定义在MSTCPiP.h有,不进行说明了,直接看代码:

 

    #include <MSTCPiP.h>

 

    DWORD retBytes;
    tcp_keepalive inKeepSetting;
    tcp_keepalive retKeepSetting;

    inKeepSetting.onoff = 1;                //探测次数
    inKeepSetting.keepalivetime = 5500;        // 首次探测开始前的tcp无数据收发空闲时间
    inKeepSetting.keepaliveinterval = 3000;    // 每次探测的间隔时间

    if (WSAIoctl(aptSock, SIO_KEEPALIVE_VALS, 
        &inKeepSetting,
        sizeof(inKeepSetting),
        &retKeepSetting,
        sizeof(retKeepSetting),
        &retBytes,
        NULL,
        NULL) != 0)
    {
        printf("WSAIoctl Error: %d/n", WSAGetLastError());
    }

 

  Linux下的方式是通过setsockopt来设置选项,见代码(代码从网络上摘录了部分):

  #include   <netinet/tcp.h> 
  ……

 

  #define SOCKET_ERROR (-1)

 

  // 以秒为单位
  int   keepAlive = 1;       //设定KeepAlive 
  int   keepIdle = 5;        //首次探测开始前的tcp无数据收发空闲时间
  int   keepInterval = 3;  //每次探测的间隔时间
  int   keepCount = 2;     //探测次数
                
  if(setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(void*)&keepAlive,sizeof(keepAlive)) == SOCKET_ERROR)

      printf("Call setsockopt error, errno is %d/n", errno);

  if(setsockopt(s,SOL_TCP,TCP_KEEPIDLE,(void   *)&keepIdle,sizeof(keepIdle)) == SOCKET_ERROR)

      printf("Call setsockopt error, errno is %d/n", errno);

  if(setsockopt(s,SOL_TCP,TCP_KEEPINTVL,(void   *)&keepInterval,sizeof(keepInterval)) == SOCKET_ERROR)

      printf("Call setsockopt error, errno is %d/n", errno);
                
  if(setsockopt(s,SOL_TCP,TCP_KEEPCNT,(void   *)&keepCount,sizeof(keepCount)) == SOCKET_ERROR)

      printf("Call setsockopt error, errno is %d/n", errno);

时间: 2024-08-07 17:09:09

socket选项自带的TCP异常断开检测的相关文章

在C#中利用Keep-Alive处理Socket网络异常断开的方法

断开|网络 最近我负责一个IM项目的开发,服务端和客户端采用TCP协议连接.服务端采用C#开发,客户端采用Delphi开发.在服务端开发中我碰到了各种各样的网络异常断开现象.在处理这些异常的时候有了一些心得,现在写出来和大家分享一下. 那网络异常断开原因主要有那些呢?归纳起来主要有以下两种: 1.客户端程序异常. 对于这种情况,我们很好处理,因为客户端程序异常退出会在服务端引发ConnectionReset的Socket异常(就是WinSock2中的10054异常).只要在服务端处理这个异常就可

TCP异常关闭研究分析

研究测试TCP断开和异常的各种情况,以便于分析网络应用(比如tconnd)断网的原因和场景,帮组分析和定位连接异常掉线的问题,并提供给TCP相关的开发测试人员作为参考. 各个游戏接入都存在一定的掉线问题,而且有的游戏项目的掉线比例还比较高,现在互娱自研游戏的网络接入基本上都用的是tconnd和ProtocalHandler组件(该组件请参考附件的<TSF4G_ProtocalHandler开发指导手册>),因此参与其掉线原因分析和研究. 在参与A项目的掉线问题研究分析过程中,tconnd增加了

Linux网络编程socket选项之SO_LINGER,SO_REUSEADDR

                       Linux网络编程socket选项之SO_LINGER,SO_REUSEADDR Linux网络编程中,socket的选项很多.其中几个比较重要的选项有:SO_LINGER(仅仅适用于TCP,SCTP), SO_REUSEADDR.   SO_LINGER 在默认情况下,当调用close关闭socke的使用,close会立即返回,但是,如果send buffer中还有数据,系统会试着先把send buffer中的数据发送出去,然后close才返回.

Socket编程中的强制关闭与优雅关闭及相关socket选项

以下描述主要是针对windows平台下的TCP socket而言. 首先需要区分一下关闭socket和关闭TCP连接的区别,关闭TCP连接是指TCP协议层的东西,就是两个TCP端之间交换了一些协议包(FIN,RST等),具体的交换过程可以看TCP协议,这里不详细描述了.而关闭socket是指关闭用户应用程序中的socket句柄,释放相关资源.但是当用户关闭socket句柄时会隐含的触发TCP连接的关闭过程. TCP连接的关闭过程有两种,一种是优雅关闭(graceful close),一种是强制关

Socket编程 (连接,发送消息) (Tcp、Udp) - Part1

原文 http://www.cnblogs.com/zengqinglei/archive/2013/04/27/3046119.html Socket编程 (连接,发送消息) (Tcp.Udp)  本篇文章主要实现Socket在Tcp\Udp协议下相互通讯的方式.(服务器端与客户端的通讯) 1.基于Tcp协议的Socket通讯类似于B/S架构,面向连接,但不同的是服务器端可以向客户端主动推送消息. 使用Tcp协议通讯需要具备以下几个条件: (1).建立一个套接字(Socket) (2).绑定服

轨迹系列——Socket总结及实现基于TCP或UDP的809协议方法

文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 在上一篇博客中我详细介绍了809协议的内容.809协议规范了通信的报文,通信的规则等,但是并没限制通信使用的传输协议.这里,我将分别介绍利用TCP和UDP传输协议来实现的809协议对接的方法. 2.TCP和UDP的介绍 TCP协议和UDP协议均是面向传输层的一种协议.而我们常说的HTTP协议则是面向应用层的一种协议. 我们常说的TCP/IP协议,则是一个协议簇

笔记本电脑连接校园宽带DRM经常出现异常断开问题如何解决

  笔记本电脑连接校园宽带DRM经常出现异常断开问题如何解决           1.打开控制面板,点击网络和Internet; 2.点击网络和共享中心--以太网; 3.点击以太网属性; 4.在项目列表中将关于WiFi的项目全部取消勾选,点击确定,重启电脑后再重新连接即可.

C语言 socket 如何发送带指针的结构体?

问题描述 C语言 socket 如何发送带指针的结构体? 发送一个带指针的结构体,我知道怎么发送? 先把结构体转换成字符串,然后发出.但是接收的时候,怎么接收到结构体中?thanks! 解决方案 发送: struct f;char *ffff[sizeof(f)];memcpy(ffff &f sizeof(f)); 接收: struct f; ffff为收到的数据 memcpy(&f ffff sizeof(ffff)); 解决方案二: C语言---结构体指针C语言--结构体中的指针C语

C++ builder中如何设计点击按钮后出现下拉选项,并且选项是带图标的。

问题描述 C++ builder中如何设计点击按钮后出现下拉选项,并且选项是带图标的. 需要设计一个带图标的按钮,按钮上显示一个向下的三角,点击向下的三角处 ,可显示下拉列表:下拉列表中显示四个图形按钮,可以选择,选择后更改下拉前的按钮图标. 解决方案 用一个第三方控件,比如http://www.tmssoftware.com/site/advdropdowncontrols.asp![图片说明](http://img.ask.csdn.net/upload/201501/21/14218282