Sockets FIN数据包出现故障并覆盖?

Sockets FIN数据包出现故障并覆盖?,sockets,networking,tcp,network-programming,protocols,Sockets,Networking,Tcp,Network Programming,Protocols,在浏览开源代码库时,我想到了一个有趣的场景。 假设在成功建立TCP连接后,TCP客户端必须发送序列号为101的数据包。相反,它发送序列号为201的FIN。现在,TCP服务器认为FIN出现故障并将其排队,等待数据包到达。 我的问题是,如果服务器接收到序列号为101、长度为150的数据包,根据RFC,TCP端点的行为应该是什么。它是否覆盖先前发送的FIN?或者服务器修剪数据包直到FIN序列号?还是取决于TCP实现 根据RFC 793中的一些段落 “3.如果连接处于同步状态(已建立, FIN-WAIT

在浏览开源代码库时,我想到了一个有趣的场景。 假设在成功建立TCP连接后,TCP客户端必须发送序列号为101的数据包。相反,它发送序列号为201的FIN。现在,TCP服务器认为FIN出现故障并将其排队,等待数据包到达。
我的问题是,如果服务器接收到序列号为101、长度为150的数据包,根据RFC,TCP端点的行为应该是什么。它是否覆盖先前发送的FIN?或者服务器修剪数据包直到FIN序列号?还是取决于TCP实现

根据RFC 793中的一些段落

“3.如果连接处于同步状态(已建立, FIN-WAIT-1、FIN-WAIT-2、关闭等待、关闭、最后确认、等待时间), 任何不可接受的段(窗口外序列号或 不可接受的确认号)必须仅引发空 包含当前发送序列号的确认段 以及一个表示下一个预期序列号的确认 ,并且连接保持在相同状态。“

“考虑处理传入段的一种自然方式是 假设他们首先测试正确的序列号(即。, 其内容位于预期的“接收窗口”范围内 在序列号空间中),然后它们通常排队 并按序号顺序进行处理

当一个段与其他已接收的段重叠时,我们重新构建 该段仅包含新数据,并调整标题字段 保持一致。”

我的响应: 请记住,如果发生这种情况,那是因为客户端的TCP行为不好。不是顺序错误,而是带有FIN标志的段中的错误序列。或者是袭击

当服务器端的TCP接收到SEQ=201的段时,它将在有限的时间内存储该段,并将发送回101的ACK,因为它正在等待该SEQ编号。
然后,当SEQ=101的段到达时,接收端的TCP在接收到SEQ=101的段后将有一个新的接收窗口。从SEQ=201的第一个到达的段中,它应该只获取字节251以外的数据(在我的测试中,它没有这样做,而是从SEQ=101的段中删除重叠字节-这可能取决于实现),如果有,并接受FIN。接收TCP将发回ACK。当服务器端的套接字关闭时,接收TCP将发回[FIN,ACK]段

为了测试它,我有一个客户机,它完全按照您所描述的做(这是通过用户空间中的原始套接字完成的,不可能用TCP套接字模拟它。服务器是一个简单的nodejs服务器),发送一个FIN段,15秒后发送上一个段。服务器读取接收到的数据,10秒后关闭套接字

这是tcpdump,您可以看到TCP服务器端响应:

    [rodolk@localhost ~]$ sudo tcpdump -i p2p1 -vv tcp
tcpdump: listening on p2p1, link-type EN10MB (Ethernet), capture size 65535 bytes
19:33:03.648216 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.56.101.16345 > 192.168.56.1.webcache: Flags [S], cksum 0x5f49 (correct), seq 523645, win 500, length 0
19:33:03.649826 IP (tos 0x0, ttl 128, id 26590, offset 0, flags [DF], proto TCP (6), length 44)
    192.168.56.1.webcache > 192.168.56.101.16345: Flags [S.], cksum 0x1ac8 (correct), seq 1576251572, ack 523646, win 8192, options [mss 1460], length 0
19:33:03.651208 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.56.101.16345 > 192.168.56.1.webcache: Flags [.], cksum 0x5091 (correct), seq 1, ack 1, win 500, length 0
19:33:03.651567 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 74)
    192.168.56.101.16345 > 192.168.56.1.webcache: Flags [F.], cksum 0x8121 (correct), seq 122:156, ack 1, win 500, length 34
19:33:03.651891 IP (tos 0x0, ttl 128, id 26591, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.56.1.webcache > 192.168.56.101.16345: Flags [.], cksum 0x5314 (correct), seq 1, ack 1, win 65392, length 0
19:33:18.652083 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 171)
    192.168.56.101.16345 > 192.168.56.1.webcache: Flags [P.], cksum 0xf973 (correct), seq 1:132, ack 1, win 500, length 131
19:33:18.652834 IP (tos 0x0, ttl 128, id 26593, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.56.1.webcache > 192.168.56.101.16345: Flags [.], cksum 0x5313 (correct), seq 1, ack 157, win 65237, length 0
19:33:28.661041 IP (tos 0x0, ttl 128, id 26594, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.56.1.webcache > 192.168.56.101.16345: Flags [F.], cksum 0x5312 (correct), seq 1, ack 157, win 65237, length 0
19:33:28.961756 IP (tos 0x0, ttl 128, id 26595, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.56.1.webcache > 192.168.56.101.16345: Flags [F.], cksum 0x5312 (correct), seq 1, ack 157, win 65237, length 0

非常有趣的问题!接收TCP将在结束时发回ACK。出站FIN是由应用程序引起的。这不是对新来的FIN的确认。@EJP,我想你说得对。让我稍后再次检查以确认,我将编辑我的回复。@EJP,我根据您的评论进行了修改。谢谢。当服务器端的套接字关闭时,它会发送一个FIN,而不是[FIN,ACK],除非还有其他东西要确认。两边的闭合是完全独立的。理论上,在TCP状态机中,它应该只是一个FIN。同意。我想这取决于实现。如果您看到tcpdump,它总是同时发送ACK。我使用nodejs TCP套接字服务器和http服务器对其进行了测试,并始终看到[FIN,ACK]。当您嗅探任何通信量时,您可以看到相同的通信量,即使没有其他数据要确认(确认号与以前的确认号相同)。反正也没什么区别。