TCP连接中的异常断开情况处理

原创 2007年06月22日 18:45:00

1.      TCP连接中可能出现的异常断开情况

假设存在这样一种情况:在两个不同的主机Machine1、Machine2系统上分别运行两个应用程序Application1、Application2,在Application1与Application2的进程中存在一个TCP链接TCPLink。它们的实际传输取决于物理链路的沟通PhysiLink。
图一:TCP通信情况模拟图
1.1程序/进程异常
如果TCPLink异常而Application1正常,TCPLink会被关掉并且告诉Application2,Application2也就关闭了该异常的TCPLink。这种情况会在TCPLink异常后的一次Socket调用中通过返回值(C/C++)或者异常代码(C#)得知。因此在做程序开发的时候比较容易处理。
1.2物理链路异常
如果出现Machine1或者Machine2任何一个系统死机:假设Machine1系统异常,此时Machine2无法知道此TCP连接的失效,并一直认为连接正常。如果网络硬件故障(如网线拔掉、交换机断电):Machine1与Machine2都无法知道此TCP连接的失效,并一直认为连接正常。
以上这两种情况在编程时会变的非常糟糕,因为TCP连接将一直被认为有效,所有对此TCP Socket的调用都会正确返回,这显然是错误的。并且这种错误情况通常会持续很久。

2.      异常断开情况影响分析

对于程序/进程异常,由于Socket调用中可以得到返回值。因此在做程序开发的时候比较容易处理。
对于物理链路异常,如果Machine1系统异常,如果Application2是FTP之类的服务器程序倒也无妨(一个连接存在时间比较长对它没有多大影响),如果是需要实时知道连接用户状态的即时通讯类服务器或者Application2是客户端则就会产生一系列的问题了。如果Machine1与Machine2都异常,Application1和Application2都会一直等下去,两端需要进行相似的处理。

3.      异常断开情况的判断与处理

对于这种情况在MSDN里面是这样处理的,原文如下:
如果您需要确定连接的当前状态,请进行非阻止、零字节的 Send 调用。如果该调用成功返回或引发 WAEWOULDBLOCK 错误代码 (10035),则该套接字仍然处于连接状态;否则,该套接字不再处于连接状态。
但是,在试验中发现,这种处理方法在很多时候根本无效,尤其对发生在物理链路层上的问题,很多情况下无法检测出网络已经异常断开了。
下面探讨一下能够使用的判断与处理方式以及优缺点。
1 
2 
3 
3.1定时发送简单约定帧
一般是服务器程序和客户端程序达成某种协议,客户端定时向服务器发送很小的数据包,即约定的简单帧,来告诉自己的状态,而服务器端程序则需要在每次收到用户的后更新用户超时的时间计数,当用户的时间计数超过指定时间,就可以认为这个用户已经系统异常终止,而终止之间的连接,并转告其他用户。客户端也可以通过接收服务器端返回的小数据包来判断服务器端的状态。
3.2Ping + Send/Receive
Ping命令来判断网络本身状态,即确定物理链路层的状态。同时,用应用程序层的Send和Receive来进行程序/进程异常的判断。通过这两种方式的组合,一般能够正确得到网络的状态。当网络发生故障时,能够准确的定位其状态。
但是,当网络正常、应用程序正常时,对端的操作系统的设置可能会影响上述判断。即,当对端禁止向其发送Ping命令时,我们Ping的结果将始终为不通。考虑这种情况下,该方法存在一定的缺陷。
3.3KeepAlive-Timer
由于在应用层进行判断存在各种困难,那么是否可以考虑使用TCP底层的一些特性呢?通过思考,我想到可以利用TCP底层协议的KeepAlive-Timer进行网络状态的判断。但是需要改造。通过改造后,这将是一个比较可靠的判断方式。这将在下面作为重点单独介绍。

4.      KeepAlive-Timer

4 
4.1 TCP/IP协议结构以及底层定时器

网络协议通常分不同层次进行开发,每一层分别负责不同的通信功能。一个协议族,比如TCP/IP,是一组不同层次上的多个协议的组合。TCP/IP通常被认为是一个四层协议系统。

图二:TCP/IP协议族的四个层次以及不同层次的协议
 
上面的每一层分别负责不同的功能。链路层,通常包括操作系统中的设备驱动程序和计算机中对应的网络接口卡。它们一起处理传输媒介(如网线)的物理接口细节。网络层,处理分组在网络中的活动。运输层主,要为两台主机上的应用程序提供端到端的通信。在TCP/IP协议族中,有两个互不相同的传输协议:TCP和UDP。TCP为两台主机提供高可靠性的数据通信。它所做的工作包括把应用程序交给它的数据分成合适的小块交给下面的网络层,确认接收到的分组,设置发送最后确认分组的超时时钟等。由于运输层提供了高可靠性的端到端的通信,因此应用层可以忽略所有这些细节。应用层,负责处理特定的应用程序细节。
关键点:应用程序位于应用层,TCP协议在运输层,在数据流从运输层传递到链路层的过程中,TCP协议本身的底层实现正是我们要利用的所在。
TCP协议在实现的时候为每条连接建立了七个定时器。按照它们在一条连接生存期内出现的次序,分别为:connection establishment timer(连接建立定时器)、retransmission timer(重传定时器)、delayed ACK timer(延迟ACK定时器)、persist timer (持续定时器)、keepalive timer(保活定时器)、FIN_WAIT _ 2 timer、TIME_WAIT timer。
4.2KeepAlive-Timer (保活定时器)
在《TCP/IP协议详解 卷2:实现》中,这样描述KeepAlive-Tmer:

KeepAlive-Tmer在应用进程选取了Socket的SO_KEEPALIVE选项时生效。如果连接的连续空闲时间超过2小时,保活定时器超时,向对端发送连接探测报文段,强迫对端响应。如果收到了期待的响应, TCP可确定对端主机工作正常,在该连接再次空闲超过2小时之前,TCP不会再进行保活测试。如果收到的是其他响应,TCP可确定对端主机已重启。如果连续若干次保活测试都未收到响应,TCP就假定对端主机已崩溃,尽管它无法区分是主机故障(例如,系统崩溃而尚未重启),还是连接故障(例如,中间的路由器发生故障或电话线断了)。

4.3KeepAlive-Timer工作机理分析

1     

2     

3     

4     

5     

5.1     

5.2     

5.3     

5.3.1          保活定时器在2小时空闲后超时

收到一个报文段后,将复位连接的保活定时器,重设为2小时,并清零连接的空闲计数器。如果保活定时器超时(收到最后一个报文段2小时后),并且置位了Socket的保活选项,则TCP将向对端发送连接探测报文段。如果定时器超时,且未置位Socket的保活选项,则TCP将只复位定时器,重设为2小时,不向对端发送连接探测报文段。当然,如果应用进程调用了close,即使连接已空闲了2小时,TCP也不会发送连接探测报文段。

5.3.2          进行保活测试

当保活定时器发送连接探测报文后,如果对端无响应,TCP最多以75秒的间隔发送9个连接探测报文段。TCP在确认连接已死亡之前必须发送多个连接探测报文段的一个原因是,对端的响应很可能是不带数据的纯ACK报文段,TCP无法保证此类报文段的可靠传输,因此,连接探测报文段的响应有可能丢失。如果连接总的空闲时间大于或等于2小时加10分钟,连接将被丢弃。从0秒起,每隔75秒连续9次发送连接探测报文段,直至600秒。675秒时(定时器2小时超时后的11.25分钟)连接被丢弃。
图三:保活定时器判断对端是否可达
 
4.4利用KeepAlive-Timer
6 
7 
8 
9 
10 
10.1 
10.2 
10.3 
通过上面的分析知道,如果在2个小时没有数据传送,TCP协议会给对端发送一个Keep-Alive数据报,使用的序列号是曾经发出的最后一个报文的最后一个字节的序列号,对端如果收到这个数据,回送一个TCP的ACK,确认这个字节已经收到,这样就知道此连接没有被断开。如果一段时间没有收到对方的响应,会进行重试,每隔75秒探测一次,重试9次后,没有收到回应的话,就会断开这个连接。
但2个小时对于我们的项目来说显然太长了。我们必须缩短这个时间。
我们要做的就是,在TCP认为的空闲2小时到达之前,模拟keepAlive-Timer的数据结构,使其按照我们的要求空闲时间、探测间隔来判断TCP的连接状态。

通过利用Socket类的IOControl()函数可以达到上述的目的:在C#中,其语法为:
public int IOControl ( IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue )
其中主要参数的意义如下:
    ioControlCode
:一个 IOControlCode 值,它指定要执行的低级操作模式的控制代码。
    optionInValue
:Byte 类型的数组,包含操作要求的输入数据。

将IOControlCode的值设置为KeepAlive就可以得到对该操作的控制。对于inOptionValues的定义,可以通过查找Wsocket2的文档找到答案:它是一个如下的结构体:
Struct tcp_keepalive
{
u_long onoff; //是否启用Keep-Alive
u_long keepalivetime;  //多长时间后开始第一次探测(单位:毫秒)

u_long keepaliveinterval; //探测时间间隔(单位:毫秒)
}

在C#中,将一个tcp_keepalive结构的内容按照顺序写入Byte数组中,然后传递给IOControl函数,我们就可以使用该函数来对网络状态进行准确的判断了。
可以这样使用:在发送数据前,使用IOControl来确保物理层的状态正确,如果不正确,则通过异常捕获来得到断开的信息,然后进行必要的信息显示,主备切换等工作。

tcp连接,传输,断开详细分析

TCP 序列号和确认号详解 在网络分析中,读懂TCP 序列号和确认号在的变化趋势,可以帮助我们学习TCP 协议以及 排查通讯故障,如通过查看序列号和确认号可以确定数据传输是否乱序。但我在查阅了当前...
  • cs5512
  • cs5512
  • 2013年11月06日 16:31
  • 1122

TCP建立与断开连接那些事儿

TCP建立与断开连接那些事儿-本文详细描述了TCP建立与断开连接的过程,阐述每一个api调用背后都发生了什么,另外还针对一些错误处理,详细说明了成因。...
  • yuxin8000
  • yuxin8000
  • 2015年12月18日 10:53
  • 474

TCP连接异常断开检测

TCP是一种面向连接的协议,连接的建立和断开需要通过收发相应的分节来实现。某些时候,由于网络的故障或是一方主机的突然崩溃而另一方无法检测到,以致始终保持着不存在的连接。下面介绍一种方法来检测这种异常断...
  • zqf_office
  • zqf_office
  • 2015年05月04日 15:17
  • 468

TCP之种种连接异常

出处:http://www.cnblogs.com/wanpengcoder/p/5356776.html 1. connect出错: (1) 若TCP客户端没有收到syn分节的响应,则返...
  • jiaoyongqing134
  • jiaoyongqing134
  • 2017年05月04日 09:58
  • 120

Tcp服务端判断客户端是否断开连接

今天搞tcp链接弄了一天,前面创建socket,绑定,监听等主要分清自己的参数,udp还是tcp的。好不容易调通了,然后就是一个需求,当客户端主动断开连接时,服务端也要断开连接,这样一下次客户端请求链...
  • ranjiewen
  • ranjiewen
  • 2016年09月20日 14:14
  • 4471

TCP连接中的异常断开情况处理

1.      TCP连接中可能出现的异常断开情况 假设存在这样一种情况:在两个不同的主机Machine1、Machine2系统上分别运行两个应用程序Application1、Application...
  • wjs1033
  • wjs1033
  • 2014年07月08日 10:25
  • 2184

针对TCP连接异常断开的分析

我们知道,一个基于TCP/IP的客户端-服务器的程序中,正常情况下,我会是启动服务器使其在一个端口上监听请求,等待客户端的连接;通过TCP的三次握手,客户端能够通过socket建立一个到服务器的连接;...
  • abcd1f2
  • abcd1f2
  • 2014年07月16日 16:37
  • 403

TCP连接异常终止分析

CP的异常终止是相对于正常释放TCP连接的过程而言的,我们都知道,TCP连接的建立是通过三次握手完成的,而TCP正常释放连接是通过四次挥手来完成,但是有些情况下,TCP在交互的过程中会出现一些意想不到...
  • andylauren
  • andylauren
  • 2017年04月11日 18:57
  • 497

tcp socket 网线断开判断

有些网络应用在网线断开后重新连上的情况下  tcp socket 连接保持 ESTABLISH 状态不变,[喝小酒的网摘]http://blog.const.net.cn/a/17107.htm ...
  • pb8
  • pb8
  • 2013年11月27日 17:51
  • 4884

简单说说TCP(3) --- 断开连接四次握手

A是主动关闭方,B是被动关闭方,四次握手可以描述为: 第一次握手:A告诉B,“我要关闭连接了”。 第二次握手:B回复A,“我知道你要关闭了,但是请等一下,我还有数据没有传完,你等我消息”。 第三次握手...
  • u014324007
  • u014324007
  • 2016年04月07日 17:16
  • 2523
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:TCP连接中的异常断开情况处理
举报原因:
原因补充:

(最多只允许输入30个字)