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),则该套接字仍然处于连接状态;否则,该套接字不再处于连接状态。

但是,在试验中发现,这种处理方法在很多时候根本无效,尤其对发生在物理链路层上的问题,很多情况下无法检测出网络已经异常断开了。

下面探讨一下能够使用的判断与处理方式以及优缺点。

3.1定时发送简单约定帧

一般是服务器程序和客户端程序达成某种协议,客户端定时向服务器发送很小的数据包,即约定的简单帧,来告诉自己的状态,而服务器端程序则需要在每次收到用户的后更新用户超时的时间计数,当用户的时间计数超过指定时间,就可以认为这个用户已经系统异常终止,而终止之间的连接,并转告其他用户。客户端也可以通过接收服务器端返回的小数据包来判断服务器端的状态。

3.2Ping + Send/Receive

用Ping命令来判断网络本身状态,即确定物理链路层的状态。同时,用应用程序层的Send和Receive来进行程序/进程异常的判断。通过这两种方式的组合,一般能够正确得到网络的状态。当网络发生故障时,能够准确的定位其状态。

但是,当网络正常、应用程序正常时,对端的操作系统的设置可能会影响上述判断。即,当对端禁止向其发送Ping命令时,我们Ping的结果将始终为不通。考虑这种情况下,该方法存在一定的缺陷。

3.3KeepAlive-Timer

由于在应用层进行判断存在各种困难,那么是否可以考虑使用TCP底层的一些特性呢?通过思考,我想到可以利用TCP底层协议的KeepAlive-Timer进行网络状态的判断。但是需要改造。通过改造后,这将是一个比较可靠的判断方式。这将在下面作为重点单独介绍。

4.KeepAlive-Timer

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工作机理分析

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

通过上面的分析知道,如果在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来确保物理层的状态正确,如果不正确,则通过异常捕获来得到断开的信息,然后进行必要的信息显示,主备切换等工作。

Linux数据链路tcp失败,TCP连接中的异常断开情况处理相关推荐

  1. 几种TCP连接中出现RST的情况

    UNIX网络编程上说:产生RST的三个条件是:目的地为某端口的SYN到达,然而在该端口上并没有正在监听 的服务器:TCP想取消一个已有链接:TCP接收到一个根本不存在的连接上的分节. 几种TCP连接中 ...

  2. TCP连接中的异常情况

    TCP 保活机制( keepalive)可以在双方没有数据交互的情况,通过探测报文,来确定对方的 TCP 连接是否存活. 无数据交互的情况下的异常[主机崩溃|进程崩溃]: 1在没有开启 TCP kee ...

  3. BLE连接过程分析及异常断开0x3e错误原因分析

    我们知道BLE通信过程是建立在连接基础之上的,按角色不同可以分为蓝牙主设备.蓝牙从设备,也叫中央设备和外围设备.以下简称为主机和从机.一次蓝牙通信,通常由主机发起,从机响应.我在调试蓝牙主机程序的过程 ...

  4. TCP连接耗尽攻击异常报文攻击与防御

    TCP连接耗尽攻击与防御 TCP是面向连接的协议,其通信双方必须保持连接状态,并且通过确认.重传.滑动窗口等机制,保证数据传输的可靠性和稳定性.攻击者利用 TCP 的上述特点,利用TCP连接消耗被攻击 ...

  5. try-catch-finally中return的执行情况

    在try中没有异常的情况下try.catch.finally的执行顺序 try--- finally 如果try中有异常,执行顺序是try--- catch --- finally 如果try中没有异 ...

  6. 【案例分析】Linux和Windows在TCP数据包上的差异+网闸兼容问题引发的TCP连接失败故障分析

    1.前言 出于项目保密原因,本文所提及的IP地址并非真实IP地址,其余技术细节均与案例实际环境相同,供学习交流参考. 2.案例背景 我们前段时间接到项目现场工程师电话,对方称他们新上架了一台Linux ...

  7. 【网络通信与信息安全】之深入解析TCP连接中如何确定客户端的端口号

    一.前言 在 TCP 连接中,客户端在发起连接请求前会先确定一个客户端的端口,然后用这个端口去和服务器端进行握手建立连接.那么在 Linux 上,客户端的端口到底是如何被确定下来的呢? 事实上,我们平 ...

  8. 【Linux网络编程】TCP网络编程中connect listen和accept三者之间的关系

    00. 目录 文章目录 00. 目录 01. TCP服务端和客户端流程 02. connect函数 03. listen函数 04. 三次握手 05. accept函数 06. 附录 01. TCP服 ...

  9. 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系

    基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: connect()函数 对于客户端的 connect() 函数,该函数的功能为客户端主动连接服务器,建立连接是通过三 ...

最新文章

  1. ubuntu下codeblocks起步
  2. 文巾解题 1433. 检查一个字符串是否可以打破另一个字符串
  3. 第二篇 - EOS Currency 合约案例
  4. 连载:阿里巴巴大数据实践—数据建模综述
  5. Dlib学习笔记:解决dlib array2d转 OpenCV Mat时颜色失真
  6. java method_JAVA Method的解析
  7. HUST 1353 Dartboard
  8. oracle rpad()函数
  9. 【POJ】【2699】The Maximum Number of Strong Kings
  10. SQL Server查询数据库执行记录
  11. 通达信波段王指标公式主图_通达信股票波段王+精准买卖提示主图指标源码公式_通达信指标公式_指标公式网...
  12. idea调整代码字体大小方法
  13. 【LeetCode】3月18日打卡-Day3
  14. gitlab中创建项目组及项目
  15. 用HTML+CSS做成的一个简单网页(小兔鲜儿)
  16. 预测、迭代与优化:用AI探寻组合优化问题最优解
  17. 航班管理系统-机票预订
  18. 监管科技与证券基金行业智能生态
  19. 为什么采购订单管理非常重要?
  20. 微信小程序 python社区疫情防控系统

热门文章

  1. 微服务中的熔断、限流、降级
  2. 工厂模式(女娲造人)
  3. html字体竖排旋转180度,css3+jq--小箭头旋转180度案例
  4. json 转 csv
  5. system V消息队列的使用
  6. java.sql.SQLRecoverableException:Io 异常: Connection reset
  7. 人工智能导论手写笔记(包含资源链接)
  8. 数字信号处理翻转课堂笔记3
  9. 【安卓学习之第三方库】 Aspect学习:AOP+注解
  10. 计算机怎样通过交换机接入网络,家用交换机怎么设置?网络交换机连接设置方式步骤...