【计算机网络 1】TCP 基础知识
前言
提到 TCP,许多人都会感到晦涩难懂。今天,就以一种直白的方式,讲讲 TCP 的基本内容。 马上要过年了,也不聊太复杂的知识,说些简单的。 以下内容均为原创,并且纯靠作者脑子记,所以可能有错误,欢迎指正!(大家也尽量背下来 :D) 概述
TCP,全称 Transmission Control Protocol,传输控制协议,位于传输层。TCP 是一种
面向连接的、可靠的、基于字节流的
协议。 把这些特点拆开分析,
面向连接
:在使用 TCP 传输数据之前,必须使用 Syn 数据包建立连接;而在数据传输完成后,必须使用 Fin 包断开连接。“连接”在物理层面并不存在,双方状态均为 Establish 时,连接已经产生。
可靠
:在连接的任意一方传输数据后,另一方收到数据,此时接收方必须回复 Ack 包以确认报文收到。如果发送方判断(猜测)该报文未被收到,则会重传报文。
基于字节流
:没啥好说的,发送方和接收方都可以通过 Stream 读取或写入数据;字节流可以想象成一条河流,不过里面流的是“数据”,任意一方向内写数据,操作系统便会发送数据,而操作系统读取到数据,又会转化为字节流形式,让接收方读取。 报文头部格式
TCP 报文头部中包含以下几个字段(仅列举重要内容),
序列号
:该报文的起始位置,建立连接时初始化。这也意味着 TCP 的报文顺序可以打乱。
确认应答号
:下一次“希望收到的”报文序列号。例如,收到 1 2 3 字节的数据后,确认应答号为 4;收到 1 3 4 7 字节的数据后,确认应答号为 2(因为字节 2 还未收到)。
Syn
:表示希望建立连接。
Fin
:表示希望断开连接。
Ack
:表示“报文已收到”。
Rst
:表示连接出现问题,需要立刻断开。这将会立刻设置发送方与接收方状态为 Close(正常情况下,主动关闭连接方还需等待 2RTT 的时间,避免第四次挥手的 Ack 丢包)。 历史遗留的处理
简单来说,历史遗留就是以前的 TCP 连接被网络延迟的报文。 例如,曾经有一个 Syn 114 的报文,后由于种种原因取消了该连接,换了另一个连接,Syn 值为 514,此时 Syn 114 先到达服务端,但是客户端已经“忘记了” Syn 114,于是发现服务端的确认应答号不匹配,直接 Rst 干掉了连接;随后 Syn 514 抵达服务端,按照正常步骤三次握手即可。 超时重传
网络环境错综复杂,难免遇到数据包丢失情况。因此,TCP 设计了重传方式,其中最简单粗暴的就是超时重传。 TCP 在数据包长时间未收到 Ack 时,会自动重传,而这个时间限制称为 RTO。 RTO 计算方式在此不多赘述,简单来说就是 RTO 略大于 RTT(报文往返一次的时间称为 RTT)。RTO 的值随着网络环境变化不断浮动。 而且,如果重传的报文再次超时,RTO 值会加倍。到达一定程度后,便会直接关闭连接,而且不使用 Fin 或 Rst。 快速重传
超时重传虽然也能保证报文交付,但是总有个超时时间,用户体验一般。 因此产生了快速重传,举个栗子: 客户端发送 Seq 1 2 3 4 5,而 Seq 2 丢包,此时服务端收到 1 3 4 5。由于缺少 Seq 2,所以服务端 Ack 均回 2。 客户端收到连续的 Ack 2,认为 Seq 2 丢包,则会进行重传,此时服务端回 Ack 6。 不过,就上面的例子,客户端能否判断,仅仅是 Seq 2 丢包,还是 Seq 2 3 4 5 丢包?显然不行。于是便产生了 SACK。 SACK 会在 Ack 报文中附带接收方缓存的地图。例如,收到了 1 3 4 5,便会带上 SACK 3-5,说明 3 4 5 均收到,而 2 未收到。 还有更进一步的 D-SACK,能够让双方清楚,是数据丢失,还是 Ack 丢失,还是被网络延迟。 总结
本期内容真的超级简单……更难的滑动窗口、流量控制、拥塞控制,都在后面呢…… 好了,1500 字了,先水到这里吧。