• 序号:
    • 数据段中第一个字节在数据流中的位置编号
  • 确认号:
    • 期望从另外一边收到的下一个字节的序号
    • 累积确认

三次握手建立连接

  • 客户端发送 SYN 请求建立连接,指定初始序号。
  • 服务器回复 SYN 和 ACK 同意连接,指定服务端初始序号。
  • 客户端回复 ACK 表示收到,可能包含数据。

四次挥手关闭连接

  • 客户端发送 FIN 请求关闭连接(不能发送只能接收数据了)
  • 服务器回复 ACK 并进行扫尾工作(扫尾时还可以发送数据)
  • 服务器回复 FIN 表示可以关闭了
  • 客户端回复 ACK 表示收到,随后进入超时等待

MSS(最大数据段长度): TCP 报文段中数据字段的最大长度,而 MSS 通常根据 MTU(最大链路层帧)来设置。

流量控制

  • 接收方在 TCP 头部消息中 rwnd 字段 ” 通知 ” 发送方剩余缓存区大小
  • rwnd 为零的时候还会继续发送探测报文
    • 如果后续接收方缓冲区有空间了(例如应用读取了数据),​​接收方需要通知发送方更新窗口​​。但此时如果双方都没有数据交互,接收方无法主动发送 ACK(因为 TCP 的 ACK 通常是“附带”在数据报文中的)。发送方定期发送​​1 字节的探测报文​​(不携带实际应用数据),迫使接收方返回 ACK,并在 ACK 中携带最新的 rwnd 值。
  • 发送方限制🚦已发送但是未被确认的数据量不超过 rwnd:

设置超时

如何设置 TCP 超时值?

应该要比 RTT 长,但是 RTT 是要变化的。如果太短会产生很多不必要的重传,如果太长则在丢包产生的时候响应变慢

这里利用 RTT 估计值和安全余量设置超时

先搞一个 RTT 估计值:(每次产生的 RTT 记录为

每次 RTT 都能够刷新一个平均值(有点像那个股市的平均了)

再搞一个安全余量:

最后的超时值:

  1. ​初始值设置​​:
    • 首次计算时,EstimatedRTT 初始化为第一个 SampleRTT
    • DevRTT 初始化为 SampleRTT / 2
  2. ​超时值的下限​​:
    • RFC 6298 要求超时值至少为 ​​1 秒​​(防止过早超时)。
  3. ​重传后的退避(Backoff)​​:
    • 若发生超时重传,下次超时值会加倍(类似指数退避)。

快速重传

收到 3 个对同样报文段的确认,则认为该报文段之后的数据丢失,启动快速重传:在定时器超时之前重发

拥塞控制

Tahoe

  • 慢启动:每个传输回合 cwnd 自乘 2,即每收到一个 ACK,cwnd+1MSS,若 cwnd 达到 ssthresh,进入拥塞避免状态。
  • 拥塞避免:cwnd 每个传输回合自增 1
  • 超时:超时了,当前的 ssthresh 的值设置为当前 cwnd 的一半,将 cwnd 设置为 1
  • 快速恢复: 收到了 3 个冗余 ACK,当前的 ssthresh 的值设置为当前 cwnd 的一半,将 cwnd 设置为(更新后的)ssthresh+ 3MSS(cwnd 减半加 3MSS),立即发送

Reno

丢包和 3 次冗余 ACK 都将 cwnd 设为 1 个 MSS

TCP 公平

公平的目标是每个 TCP 应该对带宽为 R 的瓶颈链路有 R/K 的平均速率

  • TCP 为什么是公平的
    • 两个竞争的会话:
    • 按照斜率 1 加性增加, 同时吞吐量增加
    • 乘性降低等比例减少吞吐量
    • 图中每一个点的横纵坐标表示两个连接的带宽利用率,它们的和是一定的。从红色线起点出发,沿着红色路径移动,最终会趋近于 y=x 所在的直线,即达到公平。

可以这么理解:

  • 加性增加时,两个连接都慢慢加窗口,方向是斜率 1(一起涨)。
  • 遇到拥塞时都等比例减少窗口(乘性减少)。
  • 在不断重复这个过程时,会自动调整到公平的状态(两个连接吞吐量相等)。