TCP 如何保证可靠性?一篇搞定!

本贴最后更新于 1926 天前,其中的信息可能已经时异事殊

TCP 可靠性

大部分应用程序在传输层的协议中选择都是 TCP。因为 TCP 能可靠的传输数据,保证数据能正确到达目的地。当然,因为可靠性的保证,导致 TCP 设计非常复杂,传输时间也会略长。

在特殊的应用领域如音频视频领域,一般采用的是 UDP。这是因为音视频对于时间是有精确要求的。假设采用 TCP,消息超时没有 ack,进行消息重发,但是这个时候可能已经过了这一帧数据的播放时间。这样的消息重传是无意义的。另外,像 DNS 查询等收发数据较短的也选择使用 UDP。

TCP 可靠性靠什么保证?

连接可靠

上次我们提到了 TCP 连接过程的三次握手四次挥手,参考谈谈 TCP 的三次握手四次挥手

还有一些异常情况,导致连接失败。比如接收方接到 TCP 传输的包,发现相应端口并不对方开放服务;再比如应用程序突然进程退出了;再比如,网络拥塞严重,重试多次无法正常收发消息。这些情况下,TCP 会主动发送一个叫 RST(reset)的消息,告诉对方,现在无法正常通信,可以直接关闭连接了,自己也会主动关闭相关连接,避免资源一直被占用。

ACK

ACK 机制也是我们常见的一种信息确认机制。当消息接收方接收到消息,返回一个对应的 ACK,发送方就知道这个消息已经处理完成。
在连接篇我们也简单提到过 ACK 的信息结构。但 TCP 中的 ACK 需要与滑动窗口相配合。在下面滑动窗口我们再详细说说。

超时重传

消息超时也就是说没有在等待时间内收到对方的 ACK 消息。这个时候,为了保证消息对方能够正确收到,我们需要将这个消息进行重新传输,如果尝试成功,则继续发送接下来的包。若尝试几次均失败,那么 TCP 会强行断开连接,发送 RST 信息。并告知应用程序连接错误。

TCP 滑动窗口机制


滑动窗口实现(图片来自网络)

滑动窗口用以解决什么问题

我们前面提到过 TCP 会将较大数据拆分成一个个小的数据包再进行发送。发送完一个包,等待 ACK,这种模式是最简单的。但是问题也很明显,慢,吞吐量低。所以我们在等待 ACK 的同时,可以继续发送接下来的包。也就是说,滑动窗口就是在发送完一个数据包后,不需要等待 ACK 消息返回,可以发送后面的数据包,解决吞吐量问题

那么发送多少呢?可以无限制的发送吗?当然不行!因为接收方能不能处理完这些数据我们也不清楚,缓冲一旦溢出,就无法接收新的消息。所以我们需要滑动窗口来告诉我们要发送多少数据才是合适的。

滑动窗口的类别

  • 可用窗口。即上面图片所说,窗口的范围内可能有各种状态的包。已经收到 ACK 的包,可用窗口会移动到最新的已收到 ack 的后面,发送后面的包。每次发送完包 或者 收到 ACK,数据包的状态也会改变,可用窗口也会随着更新。
  • 发送窗口。简单说来,这个窗口代表了接收方能够接受的数据量。发送窗口的大小是接受方传给发送方的。发送窗口的更新,是随着接收方应用程序已经将数据读取完成后,清空部分缓冲区,使得可以接收更多数据,这个时候可以把大小更新发送给其接收方(因为 TCP 是全双工通信,所以发送方接收方角色经常互换,描述起来比较费劲。此处接收方指的是向该服务发送数据的发送方...)

发送窗口的数据发送异常处理

上面我们简单提到了发送窗口接收到 ACK 消息后会根据情况移动。那么有没有可能接收方先接收到后面的数据包,返回了后面数据包的 ACK,导致发送窗口移动后,数据发送异常呢?

其实这个问题是在接收方进行处理的,接收方如果发现当前的数据并不是接着上次的数据包来的,比如收到了 1,2,4,未收到 3,那么接收方会返回 2 的确认信息,而不是 4 的。
再思考下,如果窗口够大,4 后面也传输了很多数据包,那么这些数据包都不能被确认,只能等待 3。如果一个发送窗口内丢失了不少包,那么尝试重新传会比较浪费时间,因为这个重新传输需要等着数据的发送方发现超时才会重发。重发的过程中,也有可能之前的发送未确认的一些数据也会超时,那么等待超时 & 重发都是比较浪费时间。

选择重发的策略我们可以直接发送丢失包及丢失包后面所有的数据包。这个量比较大的时候必然会占用网络资源。那么有没有更好的方式去处理重发呢?毕竟 4 已经收到了,能不能只发丢失的片段呢?可以,如果双方都支持 SACK (Selective ACK)的话。那么收到 4 之后,会返回一个 SACK 告诉发送方,我已经收到你发的 4 了,但是呢,有一段数据 3 你没给我发过来,需要重发~ 这样就解决重发过多的问题了

总结

TCP 在可靠性上下了很大的功夫,可靠性也增加了设计的复杂度。
保证可靠性的重点就是滑动窗口机制,ACK & 超时重传等机制都在滑动窗口的工作过程中体现。

TCP 非常复杂,我们还有很多的细节没提到,比如 TCP 标志位的其他标志、TCP 其他参数选项等等,有兴趣的同学也可以自己研究看看。

  • TCP
    32 引用 • 38 回帖 • 2 关注
  • 网络
    138 引用 • 177 回帖 • 4 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...