计算机网络:传输层(下)

142 阅读3分钟

日新计划6月更文 Day 9

  上文提到 UDP 是对 IP 协议的简单扩展,具有无连接、不可靠的特性。接下来我们来介绍面向连接的可靠数据传输协议 TCP(Transport Control Protocol,传输控制协议)「RFC 793, RFC 1122, RFC 1323, RFC 2018, RFC 2581」。

  TCP 是点对点(Point to Point)、可靠有序、流水线(Pipelined)式、全双工(Full Duplex)、面向连接(Connection-Oriented)、具有流量控制(Flow Controlled)的数据传输协议,其实现非常复杂,下面仅对其部分特性的实现进行探讨。

  TCP 的数据段格式更加复杂:

源端口号(16 bits) 目的端口号(16 bits)
sequence number(32 bits)
acknowledgement (32 bits)
head len(4 bits) not used(6 bits) URG ACK PSH PST SYN FIN receive window(16 bits)
checksum(16 bits) Urg data pointer(16 bits)
options (16 bits * n)
application data (16 bits * n)

  其中“sequence number”(Seq)表示该数据段的编号,根据发送方发送顺序依次递增;“acknowledgement ”(Ack)表示该端希望接收到的下一个数据段的编号。

  如果某个数据段丢失(接收方一段时间内未收到),该方后续发送的数据段的 Ack 始终是该数据段的编号直至对方重传并收到该数据段。

  为了避免发送方发送过多,接收方在给发送方的回复中会有rwnd(Receiver Window)来标识接收方空闲缓冲区大小,使用滑动窗口算法进行限速;为了防止拥塞,双方协商cwnd(Congestion Window,拥塞窗口)来决定发送速度。

  在TCP通信建立初期,处于慢启动(slow start)阶段,初始 cwnd = 1MSS(Maximum Segment Size,最大报文长度),每收到一个 ACK,cwnd ++,直到 cwnd 达到阈值 ssthresh。该过程正常情况下传输速度呈指数级增长。

  cwnd 达到阈值 ssthresh 后,cwnd 随时间均匀增大,每经过一个 RTT cwnd++,称为拥塞避免(Congestion Avoidance )。

  当收到三个相同 ACK 或超时但未收到某个数据段的 ACK 后,发送方立即重传该数据段并将 ssthresh 修改为 当时 cwnd 的一半,将 cwnd 修改为 1,这称为“快重传”(Fast Retransmit)。

  上述是 TCP 早期拥塞控制 Tahoe,后期的 Reno 引入了“快恢复”(Fast Recovery),即在收到三个相同 ACK 后不将 cwnd 置为 1 而是置为 修改后的 ssthresh + 3。

  建立 TCP 连接需要进行三次握手:

  • 客户端向服务端发送 SYN=1,Seq=x(每次随机选择一个)的 TCP 数据段
  • 服务端向客户端发送 SYN=1,ACK=1,Seq=y(同样每次随机选一个),Ack=x+1 的 TCP 数据段
  • 客户端向服务端发送 ACK=1,Seq=x+1,Ack=y+1 的 TCP 数据段

  结束 TCP 连接需要进行四次挥手:

  • 客户端向服务器发送 FIN=1,Seq=u 的 TCP 数据段,请求断开连接
  • 服务器向客户端发送ACK=1,Seq=v,Ack=u+1 的数据段
  • 服务端发送 FIN=1,ACK=1,Seq=w,Ack=u+1 的数据段,请求断开连接
  • 客户端发送 ACK=1,Seq=u+1,Ack=w+1 的数