应用层如何感知传输层链路故障

应用层如何感知传输层链路故障

比如,一条普通的http连接底层依赖了一条普通的tcp连接,当某些故障导致tcp断掉了,http如何感知呢?

结论:tcp连接本质上是逻辑上的连接,依靠两边的操作系统内核维护了一些变量来表示连接的不同状态,所以只有在两端间真正有数据包传送的时候,才可能会改变现有的逻辑状态到一个新状态。

以下实验已将socket keepalive关闭

实验1:应用层有新数据发送时

实验过程

  1. client 与 server 建立TCP连接

  2. 通过scapy构造RST包“欺骗”server关闭连接来模拟链路故障,此时client并不知情server端已关闭(send(IP(dst=“192.168.57.3”)/TCP(sport=42752, dport=12345, seq=992635624, flags=“R”)))

  3. client发送数据

  4. 可以看到server由内核代为返回了RST包

抓包详情如下:

在这里插入图片描述

其中称192.168.57.100为client,192.168.57.3为server

每个包解释如下:

  • seq=1-3,TCP三次握手建立连接

  • seq=12,用scapy构造的欺骗包,让server误以为client要断开连接,从而server释放掉该tcp连接

  • seq=13,client认为连接仍然正常,使用send()函数发送字符串"hello world"给server

  • seq=14,server端内核发现13号数据包对应的socket不存在,遂发送RST包提示对方该连接无效,也就是14号包

实验2:应用层要接受数据

实验过程

  1. client 与 server 建立TCP连接

  2. 通过scapy构造RST包“欺骗”server关闭连接来模拟链路故障,此时client并不知情server端已关闭

  3. client 进入 recv开始阻塞接收

  4. 实验效果:client一直阻塞在recv处

抓包详情如下:

在这里插入图片描述

可以看到在发送seq=20的RST欺骗包后,随后双方无任何数据沟通。导致了server端TCP连接已关闭,但client端不知情,一直阻塞。

这里的“client端不知情”说的稍微明白些其实是“client 的内核不知情”,如果在“内核知情后”,再进入recv,会有什么效果呢?

实验3:应用层发送数据后再接收数据

开篇提到的http是比较符合这种情况的,因为http是由request(发送数据)和response(接受数据)构成的

实验过程

  1. client 与 server 建立TCP连接

  2. 通过scapy构造RST包“欺骗”server关闭连接来模拟链路故障,此时client并不知情server端已关闭

  3. client发送数据

  4. client接收数据

  5. 实验效果:send发送返回成功,recv返回“Connection reset by peer”

抓包详情:

在这里插入图片描述

数据包情况跟实验1完全一致,client发送了15号数据包,server返回16号RST包通知到client内核,待到client执行recv时,内核直接返回“Connection reset by peer”的信息提示应用层。

你可能感兴趣的:(TCP,linux,网络,tcp/ip,java)