“正常”的 TCP 握手如下所示:
MachineA → SYN → MachineB
Machine B → SYN,ACK → MachineA
MachineA → ACK → MachineB
这意味着对于每个步骤,预计将在数据包中设置一个标志(或一组标志)。
当预期标志存在时,额外标志是否会被丢弃,或者带有额外标志的数据包是否被视为不正确?换句话说,以下序列是否会被视为MachineB
完整、正确的握手?
MachineA → SYN → MachineB
Machine B → SYN,ACK → MachineA
MachineA → ACK,RST,FIN → MachineB
ACK
出现在最后一个数据包中(因此握手可以被视为已完成),但还有一个RST
andFIN
标志(这只是无关标志的示例)。
我的问题是一般性的 - 初始握手只是一个例子,我对丢弃或不超过其他序列的额外标志的一般情况感兴趣。
从技术上讲,它们本身都不是无关的,即使您示例中的完整组合确实过多。
“握手的第 3 个数据包需要 ACK”过于简单化了 – TCP 握手实际上从未被指定为具有这种严格的
SYN
→SYN,ACK
→ACK
形式。相反,每个标志具有特定的功能和特定的状态转换,这导致具有这种形式的典型握手。更一般地说,握手的功能是:
SYN
,机器B发送ACK
s。SYN
,机器 AACK
发送。即使
ACK
from machine B 与 合并SYN
,这些仍然只是单独的操作,甚至规范将其描述为逻辑上的四向握手,其中某些步骤“可以组合”成三向握手 -通常是这样,但是这并不是一成不变的。例如,两台主机
SYN
同时发送它们的 s 是合法的,交叉路径(我认为这在实践中不会发生),导致SYN
⇄SYN
/SYN,ACK
⇄交换——在 TCP 中SYN,ACK
称为“同时打开”。另一方面,虽然规范确实规定接收到的 SYN 应该随后发送 SYN,ACK 作为回报,但如果在第二步中只收到一个
ACK
without ,它仍然不是一个错误 – 它是一个有效的 ACK,尽管它有SYN
对推进握手没有影响。同样,
FIN
→FIN,ACK
→ACK
序列由两个不同的FIN
→ACK
序列组成,其中每台机器都确认接收到的 FIN,并且有一个“半封闭”连接是合法且常见的,其中一侧已发出 FIN,而另一侧仅确认它,但继续发送数据。所以关于你的例子:
当机器 B 收到第 3 个数据包时,它处于 SYN-RECEIVED 状态。
允许在此时进行设置
RST
,这将在没有完全建立连接的情况下关闭连接 – 不是作为无效的握手数据包,而是作为有效的 RST。该规范没有说明此时是否检查 FIN——只有在没有 RST 的情况下才会进行检查。
也允许在此时进行
FIN
设置,如果 RST 不存在,则与连接处于 ESTABLISHED 状态具有相同的效果。(请注意,同一部分只说“发送 FIN 的确认”;它没有说任何有关发送另一个 FIN 作为回报的信息——这必须由关闭套接字的软件显式完成。)
在同一个数据包上同时存在FIN 和 RST 确实很奇怪,但在这种情况下,RST 将首先生效,并且(按照规范中详细说明的算法)永远不会检查 FIN。
不存在“额外标志”的一般情况;该规范列出了接收器在每个状态下应检查哪些标志,并且响应取决于标志和状态。例如,CLOSING 状态下的 URG 标志被指定为“忽略 URG”,而在 SYN-SENT 状态下则照常处理(因为 SYN 数据包允许包含常规数据)。