TCP 可靠性

TCP Reset Attack

Untitled

TCP协议虚拟了文本流(byte stream)的通信,TCP 协议 确保了数据到达的顺序与文本流顺序相符。 我们可以一边接收,一边将文本流存入文件系统。这样,等到“流”接收完了,硬盘写入操作也已经完成。如果采取 UDP 的传输方式,我们需要等到所有的数据到达后,进行排序,才能组装成大的文件。

流的要点是次序 order,TCP 协议封装到 IP 包的不是整个文本流,而是 TCP 协议所规定的片段(segment),一个 TCP 片段同样分为 header 和 payload. TCP片段的头部(header)会存有该片段的序号(sequence number)。这样,接收的计算机就可以知道接收到的片段在原文本流中的顺序了,也可以知道自己下一步需要接收哪个片段以形成流。比如已经接收到了片段1,片段2,片段3,那么接收主机就开始期待片段 4。如果接收到不符合顺序的数据包(比如片段8),接收方的 TCP 模块可以拒绝接收,从而保证呈现给接收主机的信息是符合次序的“流”。

可靠性

IP 协议是不可靠的,所以 IP 数据包可能在传输过程中发生错误或者丢失。而 IP 传输是"Best Effort" 式的,如果发生异常情况,我们的 IP 数据包就会被轻易的丢弃掉。另一方面,如果乱序(out-of-order)片段到达,根据我们上面说的,接收主机不会接收。这样,错误片段、丢失片段和被拒片段的联手破坏之下,接收主机只可能收到一个充满“漏洞”的文本流。TCP 的补救方法是,在每收到一个正确的、符合次序的片段之后,就向发送方(也就是连接的另一段)发送一个特殊的 TCP 片段,用来知会(ACK,acknowledge)发送方:我已经收到那个片段了。这个特殊的 TCP 片段叫做 ACK 回复。如果一个片段序号为L,对应 ACK 回复有回复号L+1,也就是接收方期待接收的下一个发送片段的序号。如果发送方在一定时间等待之后,还是没有收到 ACK 回复,那么它推断之前发送的片段一定发生了异常。发送方会重复发送(retransmit)那个出现异常的片段,等待 ACK 回复,如果还没有收到,那么再重复发送原片段... 直到收到该片段对应的 ACK 回复(回复号为 L+1 的 ACK)。当发送方收到ACK回复时,它看到里面的回复号为 L+1,也就是发送方下一个应该发送的 TCP 片段序号。发送方推断出之前的片段已经被正确的接收,随后发出 L+1 号片段。ACK 回复也有可能丢失。对于发送方来说,这和接收方拒绝发送ACK回复是一样的。发送方会重复发送,而接收方接收到已知会过的片段,推断出 ACK 回复丢失,会重新发送 ACK 回复。

Untitled

滑窗 sliding window

上面的工作方式中,发送方保持发送->等待 ACK ->发送->等待 ACK...的单线工作方式,这样的工作方式叫做 stop-and-wait。stop-and-wait 虽然实现了TCP通信的可靠性,但同时牺牲了网络通信的效率。在等待 ACK 的时间段内,网络都处于闲置 (idle) 状态。我们希望有一种方式,可以同时发送出多个片段。然而如果同时发出多个片段,那么由于 IP 包传送是无次序的,有可能会生成乱序片段(out-of-order),也就是后发出的片段先到达。在 stop-and-wait 的工作方式下,乱序片段完全被拒绝,这也很不效率。毕竟,乱序片段只是提前到达的片段。我们可以在缓存中先存放它,等到它之前的片段补充完毕,再将它缀在后面。然而,如果一个乱序片段实在是太过提前(太“乱”了),该片段将长时间占用缓存。我们需要一种折中的方法来解决该问题:利用缓存保留一些“不那么乱”的片段,期望能在段时间内补充上之前的片段(暂不处理,但发送相应的 ACK);对于“乱”的比较厉害的片段,则将它们拒绝(不处理也不发送对应的 ACK)。

滑窗 sliding window 被同时应用于接收方和发送方,以解决以上问题。发送方和接收方各有一个滑窗,当片段位于滑窗中时,表示 TCP 正在处理该片段。滑窗中可以有多个片段,也就是可以同时处理多个片段。滑窗越大,同时处理的片段数目越多(当然计算机也必须分配出更多的缓存供滑窗使用)窗口大小就是指无需等待确认应答,而可以继续发送数据的最大值

窗口的实现实际上是操作系统开辟的一个缓存空间,发送方主机在等到确认应答返回之前,必须在缓冲区中保留已发送的数据。如果按期收到确认应答,此时数据就可以从缓存区清除。

假设窗口大小为 3 个 TCP 段,那么发送方就可以「连续发送」 3 个 TCP 段,并且中途若有 ACK 丢失,可以通过「下一个确认应答进行确认」。如下图:

Untitled

TCP sliding window-XNDg1NDUyMDUy.mp4

TCP 3-Way Handshake

TCP Flags:TCP 首部中有 6 个标志比特,其中多个可同时被设置为 1,主要用于操控 TCP 的状态机,依次为 URG,ACK,PSH,RST,SYN,FIN。含义:

ACK(Acknowledgement):此标志表示应答域有效,就是说前面所说的 TCP 应答号将会包含在 TCP 数据包中;有两个取值:0 和 1,为 1 的时候表示应答域有效,反之为 0