15-TCP 协议(半打开)

1. 半打开(Half-Open)

如果一方已经关闭或异常终止,而另一方却对此毫不知情,这种连接就称为半打开的。

比如:其中一端突然断网了,或者停电导致的异常关机。

假设在主机 A 和 B 之间建立了一条 TCP 连接,由于停电导致主机 B 异常关机。接下来,我们分三种情况讨论,A 此时继续给 B 发数据,会有什么现象。

  • B 仍然关机
  • B 开机,但是未启动服务
  • B 开机并重新启动了服务

2. 实验

serv 程序路径:unp/protocol/tools/winserver/tcp_server.cpp
client 程序路径:unp/protocol/tools/winclient/client_server.cpp

首先,我们要模拟出这种现象,没有必要非得关机,拨了网线就行了。

主机 A : 192.168.166.107.
主机 B:192.168.166.14

  • 在主机 B 上启动服务:
tcp_server.exe 192.168.166.14 5000
  • 在主机 A 上打开 OmniPeek 抓包
  • 主机 A 上启动客户端:
tcp_client.exe 192.168.166.14 5000

输入几行数据后,正常回显。

  • 将主机 B 断网

2.1 B 仍然关机(仍然断网的状态)


这里写图片描述
图1 read 出错,错误码 10053

错误码 10053 表示 ECONNABORTED,表示连接异常。我们看看抓的数据包,见图 2.


这里写图片描述
图2 最后一个 tcp 报文,重传了 4 次,最后异常断开

2.2 B 开机但是服务未开启


这里写图片描述
图3 向对端发数据


这里写图片描述
图4 最后一个报文 zaibuzai 重传了 6 次,最后一次向对端发送了 RST 段

2.3 B 开机,且重新启动了服务

在这里,我把 A 主机设定成 192.168.166.14
B 主机设定成了 192.168.166.107

因为我的 OmniPeek 安装在了 107 这台机器上,现在我想抓服务器上的数据。


这里写图片描述
图4 最后一次发送 tcp 时,客户端处于半打开状态

错误码 10054 表示 ECONNRESET. 即连接被重置。


这里写图片描述
图5 服务器收到了对端的数据 tcp 后,回送 RST 段

图 5 中,1 号到 9 号(包含 9 号)数据包都是断网前 A 和 B 之间建立的连接。然后 B 重新启动了服务,此时 B 收到了 A 发来的数据,由于此时 B 已经重新启动,它并不知道 A 发来的数据是哪个连接,所以直接回送了 RST 段。

有人好奇我为什么要把 107 主机和 14 主机对换,让 107 做服务器。。。因为之前尝试着让 14 主机做服务器,然后断网重启,让 107 给 14 发数据,但是并没有得到 14 的回应的 RST 段,我猜测这可能和系统有关,我的 14 主机是 win10 系统。

3. 结果分析

在上面我们用实验演示了三种情况,很多同学可能不太想看,这里我直接说结论吧:

处于半连接的 A 向主机 B 发送数据:

  • 如果主机 B 仍然断网或者已经连接上网络,但是服务未启动,A 向 B 发送数据,经过数次超时重传后放弃连接,并发送 RST 段给对方(不一定非得发送,这系统实现有关)。
  • 如果主机 B 已经连接上网络且重新启动了服务,A 向 B 发送数据,B 收到后因为不认识这个连接,向 A 发送 RST 段。

希望同学们自己动手做做实验,看看你的结果是否和我的有差异,欢迎交流,你可以在博客下方评论,也可以加入 QQ 交流群:610441700

4. 总结

  • 知道半打开的概念
  • 半打开的一端向对端发送数据的后果