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. 总结
- 知道半打开的概念
- 半打开的一端向对端发送数据的后果