# TCP/UDP

# TCP

:传输控制协议(Transmission Control Protocol)

  • 属于传输层协议,规定了网络上的主机之间如何传输数据。
  • 采用 C/S 架构,需要一方作为服务器保持运行。
  • 特点:
    • 全双工通信。
    • 面向连接:通信双方在通信之前要先建立连接,作为信道。
    • 传输可靠:
      • 会确认对方是否收到消息,如果未收到则自动重发。
      • 可进行差错控制,如果对方收到的消息出错,则自动重发。
      • 发送的数据包带有序号,接收方可按顺序处理。
      • 可实现流量控制、拥塞控制。
  • 大部分应用层协议都是基于 TCP 进行通信的,比如 HTTP、FTP、SMTP 等。

# 数据包结构

TCP 数据包的结构如下:

  • Source Port :源端口,长度为 16 bit 。
  • Dest Port :目标端口,16 bit 。
  • Seq number :序列号,32 bit ,用于保证消息顺序。
  • Ack number :确认号,32 bit ,表示期望收到的下一个序列号,用于标识符 ACK=1 的情况。
  • Data offset :偏移量,4 bit 。表示 Payload 的起始坐标,即 TCP Header 的总长度。
  • Reserved :保留给未来使用,3 bit ,默认值为 0 。
  • Flag :标志符,9 bit 。每个 bit 代表一个标志位,默认值为 0 。
    • NS
    • CWR
    • ECE
    • URG=1 :表示该数据是紧急数据,应该被优先处理。
    • ACK=1 :表示确认。
    • PSH=1 :表示发送方应该立即将该数据打包成一个 TCP 数据包发送,接收方也应该立即将该数据上报给上层程序。
      • TCP 模块在发送数据时,一般会等发送缓冲区满了,才打包成一个 TCP 数据包发送。同理,接收数据时也一般会等接收缓冲区满了才上报。
      • 一般一个应用层的报文会被切分成多个 TCP 数据包发送,最后一个 TCP 数据包会设置成 PSH=1 。
    • RST=1 :用于重新建立 TCP 连接,也可用于拒绝连接。
    • SYN=1 :用于建立 TCP 连接,开始同步。
    • FIN=1 :用于断开 TCP 连接。
  • Window size
  • Checksum :校验和,16 bit 。
  • Urgent pointer
  • Options
  • Payload :有效载体,即该数据包要传递的实际数据。
    • Payload 之前的其它数据都只是用于描述 TCP 数据包的元数据,称为 TCP Header 。
    • 以太网中网卡的 MTU 通常设置为 1500 ,因此如果 TCP 报文超过该长度,转换成 IP 数据包时就需要拆分成多份。

# 建立连接

  • 建立 TCP 连接时需要经过三个步骤,称为 "三次握手" :

    1. 主机 A 发送一个 SYN=1 的 TCP 包,表示请求连接。
    2. 主机 B 收到后,回复一个 SYN=1、ACK=1 的 TCP 包,表示允许连接。
    3. 主机 A 收到后,发送一个 ACK=1 的 TCP 包,表示正式建立连接。
      • 主机 A 收到第 2 步发送的包时,证明了自己发送的包能被对方接收,而对方发送的包也能被自己接收,因此判断双方能够相互通信。
      • 主机 B 收到第 3 步发送的包时,才判断双方能够相互通信。
  • 主动连接方称为 client ,被动连接方称为 server 。

    • 通信双方都要发送一个 SYN、一个 ACK 。
    • 建立连接之后,双方便可以开始正式通信,发送任意个包含有效载体的 TCP 数据包。

# 断开连接

  • 断开 TCP 连接时需要经过四个步骤,称为 "四次分手" :
    1. 主机 A 发送 FIN ,表示请求断开连接。
    2. 主机 B 收到后,先回复 ACK ,表示同意断开连接。
      准备好了之后也发送 FIN ,请求断开连接。
    3. 主机 A 收到后,发送一个 ACK ,表示自己已经断开连接。
    4. 主机 B 收到后,正式断开连接。
  • client、server 都可以主动断开连接。
    • 通信双方都要发送一个 FIN、一个 ACK 。

# 传输数据包

# 重传

  • 建立 TCP 连接之后,通信双方可以开始传输数据包。
    • 发送方每发送一个数据包之后,都需要接收方回复一个包含相应序列号的 ACK 包,才能确认发送成功。
  • 超时重传
    • :如果发送方发送一个数据包之后,超过 RTO(Retransmission Timeout) 时间未收到 ACK 包,则重新发送原数据包。
    • RTO 应该略大于 RTT 。例如 Linux 会根据网络实时的平均 RTT ,动态设置 ERO 。
      • 往返时间(Round Trip Time ,RTT),表示从发出数据包到收到回复的耗时。是端到端延迟的两倍。
    • 超时的常见原因:
      • 网络延迟突然变大
      • 发送的数据包丢失
      • 回复的 ACK 包丢失
  • 快速重传
    • :如果发送方发送一个数据包之后,没有受到 ACK 包,但之后发送的 3 个数据包都收到 ACK 包,则认为前一个数据包发送失败,立即重传。

# 流量控制

  • 滑动窗口
    • :接收方将接收窗口的大小告诉发送方,发送方由此确定发送窗口,可以每次发送多个数据包,再等待确认。
    • 这可以实现流量控制,控制传输速度。
  • 发送窗口
    • :指发送方能同时发送的数据包数,即最多允许多少个数据包等待确认,此时不允许发送新的数据包。
    • 它不能超过网络允许带宽、接收方的接收缓冲区,否则会丢包。
    • 发送窗口取决于接收窗口,近似相等

# 拥塞控制

  • 网络拥塞:当网络延迟变大、发生丢包时,会引发超时重传,但重传的数据包又会增加网络负载,导致延迟更大、丢包率更高。

  • 为了减轻网络拥塞,发送方会动态计算一个拥塞窗口,并限制发送窗口不能大于接收窗口或拥塞窗口。

  • BBR

    • :Google 于 2016 年发布的一种 TCP 拥塞控制算法。在延迟超过 100ms 、丢包率超过 1% 的场景下,能在发送 TCP 包时明显提高吞吐量、降低延迟。
    • 当网络链路拥塞时,传统的拥塞控制算法 Reno、Cubic 会将数据包放到缓冲区再发送,因此增加了延迟。而 BBR 算法会避免使用缓冲区。
    • Linux 内核 4.9 加入了 BBR 算法,可通过 sysctl 启用。
    • 拥塞控制算法只作用于 TCP 通信的一方,因此发送方、接收方可以采用不同的算法。

# UDP

:用户数据报协议(User Datagram Protocol)

  • 特点:
    • 全双工通信。
    • 面向无连接。
    • 传输不可靠。
  • UDP 与 TCP 对比:
    • UDP 没有 TCP 的诸多功能,更像是 IP 协议,只是简单地发送数据包。
    • UDP 的开销更低。比如 TCP 需要一直运行一个服务器,而 UDP 适合用作即时通信、广播消息。
    • 使用 UDP 时,如果需要差错控制等可靠性,可由应用层实现。
  • 少部分应用层协议是基于 UDP 进行通信的,比如 DHCP、DNS、SNMP、RIP 等。