TCP 服务模型(TCP Service Model)

工作流程

TCP 工作流程

  1. 应用层想要传输数据,于是调用 TCP 层并传递想要传输的数据
  2. TCP 将拿到的数据放入 TCP 段中,然后将 TCP 段传递给 IP 层(网络层)
  3. IP 层将拿到的数据封装为一个 IP 数据报并添加 IP 地址,然后将 IP 数据报传递给链路层
  4. 链路层构建链路帧,并添加链路地址(比如以太网地址),然后将其发送到网络中

双向连接的建立——三次握手

三次握手
要建立双向连接,需要经过以下流程:

  1. A 向 B 发送 Syn 信息表示请求 A 到 B 的连接
  2. B 向 A 发送 Ack 信息表示同意 A 到 B 的连接,同时附带 Syn 信息表示请求 B 到 A 的连接
  3. A 向 B 发送 Ack 信息表示同意 B 到 A 的连接

同时两端会各自维护一个状态机,后面会讲到

双向连接的断开——四次挥手

四次挥手
要断开双向连接,需要经过以下流程:

  1. A 向 B 发送 Fin 信息,表示想要断开 A 到 B 的连接
  2. B 向 A 发送 Ack 信息,表示同意断开 A 到 B 的连接,同时可能附带还未发送完的数据
  3. 一段时间后,B 完成了所有需要发给 A 的数据的发送,向 A 发送 Fin 信息,表示想要断开 B 到 A 的连接
  4. A 向 B 发送 Ack 信息,表示同意断开 B 到 A 的连接

TCP 为应用层提供的服务

TCP 为应用层提供的服务

  • TCP 保证数据会到达,如果传输中断,TCP 会重新发送
  • TCP 通过以下方式保证传输是可靠的:
    • 当 TCP 接收到数据时,会发送一个确认包给发送方,表示数据正确到达
    • 使用校验和来检测数据是否损坏
    • 使用序列号用于检测数据是否丢失(每个数据段头部会有一个序列号)
    • 流量控制来防止接收方过载:接收方会不断告知发送方是否可以继续发送,即告诉发送方缓冲区中还有多少空间可以接收新数据
  • TCP 会保证给应用层的数据是符合顺序的,即如果接收到的数据是乱序的,TCP 会使用序列号将数据重新排序
  • TCP 会试图在所有使用网络的 TCP 连接之间平均分配网络容量(拥塞控制机制)

TCP 段内部格式

TCP段内部格式

  • Destination Port:目标端口说明数据应该传输给接收方的哪一个应用(比如 SSH 服务就是 22 端口)
  • Source Port:源端口说明接收方应该使用哪个端口发送回数据(即接收方将发送方的源端口作为自己的目标端口)
  • Sequence:序列号表示 TCP 数据字段中第一个字节在字节流中的位置
  • Acknowledgement Sequence:
    确认序列号告诉另一端期望接收的下一个字节号,同时这也表明了该字节号前的所有字节数据均被成功接收
  • Checksum:校验和是根据整个头部和数据计算得到的,用于帮助接收方确认数据是否损坏
  • HLEN:说明 TCP 字段的头部长度为多少
  • TCP options:可选字段包含了 TCP 标准建立后新添加的头部字段,HLEN 也说明了有多少可选字段存在(通常是没有的)
  • Flags:
    • ACK:表明确认序列号是有效的,确认了之前接收到的所有数据
    • SYN:表明正在发送同步信号,即三次握手中的一部分
    • FIN:表示关闭单方向的连接
    • PSH:表示数据到达时,对方 TCP 端应该立即交付数据给应用层(这对一些时间敏感的操作很有用,比如按键操作)

TCP 连接的唯一标识

组成唯一标识的五个字段

图中的五个字段组成了 TCP 连接的唯一标识:

IPv4 头部字段中的 IP DA 和 IP SA 指定了两台机器在网络中的位置,Protocol ID 指定了传输层使用的协议为 TCP

TCP 头部字段中的 Source Port 和 Destination Port 指定了两台机器中的指定应用

然而,这样的唯一标识只有在下述条件成立时才有效:连接的两端使用唯一的源端口用于 TCP 服务。

比如主机 A 使用 20 端口用于与 B 的一个连接服务,再选择 20 端口用于另一个连接服务就会导致错误。

一般采用一个简单的方法来避免这种情况:对于每一个新增的连接,使用递增的源端口号。

但是这样做也有可能会导致错误,比如主机 A 突然新增了大量的到主机 B 的连接,端口的递增可能会超出位数限制从而绕回到一个已经使用的端口。

使用同一个端口用于两个服务,会导致接收数据的混淆。

序列号的作用

为了减少混淆的可能性,TCP 连接会在初始化时使用一个随机的序列号来引用字节流中的字节(这并不是万无一失的,但是确实减少了混淆的可能性)

由于初始化序列号的存在,三次握手时会附带相关数据,即图中的 ISN(Initial Sequence Number):

包含 ISN 的三次握手

序列号在 TCP 中的工作如图:

序列号的工作图

UDP 服务模型(UDP Service Model)

UDP 段内部格式

UDP 段内部格式

  • Checksum:校验和的使用是可选的,如果不使用,则为全零;如果使用,校验和的计算会包含 UDP 头部和数据、IPv4 头部的起止地址和UDP协议 ID(这违反了层次的清晰分离原则,但是这使得 UDP 层能够检测到被错误投递的数据报)
  • Length:至少为 8 字节,因为这是 UDP 头部的长度

UDP 的三个特性

UDP 的三个特性

  1. 无连接的数据报服务:数据的传输不需要建立连接,且数据包可能乱序到达,也可能丢失
  2. 自包含的数据报:即每个数据报包含足够多的信息,可以被独立传输、处理
  3. 不可靠传输:无确认、无丢包检测、无流量控制

总的来说,UDP 提供了一种更简单的数据报传输服务

ICMP 服务模型(ICMP Service Model)

三种确保网络层正常工作的机制

ICMP 的工作

ICMP 位于传输层,用于向网络层传递错误信息

以下为几个错误信息的示例

ping 命令是怎么使用 ICMP 的?

ping 用于测试另一台主机的活跃状态,比如在终端中运行下面这行命令

1
ping bilibili.com

便可以看到类似下面的信息

1
2
3
4
5
6
7
8
9
10
Pinging bilibili.com [198.18.0.16] with 32 bytes of data:
Reply from 198.18.0.16: bytes=32 time<1ms TTL=128
Reply from 198.18.0.16: bytes=32 time<1ms TTL=128
Reply from 198.18.0.16: bytes=32 time<1ms TTL=128
Reply from 198.18.0.16: bytes=32 time<1ms TTL=128

Ping statistics for 198.18.0.16:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms

其中的过程如图,ping 直接调用 ICMP,发送一个 ICMP 回显请求,然后接收方返回一个回显应答

ping 调用 ICMP

总结

  • ICMP 提供了网络层到终端主机和路由器的信息
  • ICMP 位于网络层上方,所以属于传输层,但是 ICMP 是为网络层服务的
  • pingtraceroute 等命令都依赖于 ICMP

端到端原则(End to End Principle)

在主机 A 到主机 B 的连接中,网络其实可以做很多事情来进行优化,比如压缩数据、重新格式化或者优化请求、添加安全措施等等,但是通常来说,网路并没有怎么做,这是为什么?因为要遵循 端到端原则

端到端原则的来源

之所以会有端到端原则,是因为以下这样一个例子:

一个栗子

文件从源主机到目标主机,每两个机器之间的链路都有错误检测。

理想状况是,传输中出现错误,检测到错误,拒收文件然后重新发送。

但是问题在于链路上的错误检测只能检测传输层面的错误,如果出现内存层面的错误就无法检测了,如图

内存层面的错误

确保文件正确到达的唯一方法就是进行端到端的检查。

端到端功能之外的优化

考虑无线链路和有线链路的可靠性,有线链路的传输往往是极其可靠的,而无线链路的传输则并没有那么可靠。

链路层的重传机制可以通过有效地检测和纠正错误、减少丢包、提高数据的可靠性,极大地优化无线链路的性能。

错误检测(Error Detection)

错误检测 有三种方法:

  • Checksum(校验和)
  • CRC(循环冗余校验码,cyclic redundancy code)
  • MAC(消息认证码,message authenciation code)

Ethernet 会在尾部增添一个 CRC,TLS 在尾部增添一个 MAC

IP 则在数据头部增添一个 Checksum

三种错误检测方法,各有优劣

Checksum

Checksum 是一种简单的错误检测方法,它通过对数据内容进行求和(通常是按字节、按块或按固定长度的单位)得到一个和校验值。然后,发送端和接收端都计算并比较这个校验和值,以判断数据是否在传输过程中发生了错误。

  • 优点:实现简单,计算量小,计算速度快
  • 缺点:鲁棒性低,无法检测偶数个比特位的错误以及其他的特定错误

Checksum 主要用于简单的数据完整性检测,例如传输协议(如IP、TCP、UDP)或存储系统中的错误检测。

CRC

CRC 是一种比 Checksum 更强大的错误检测方法,它基于多项式除法。数据被看作一个大的二进制数,使用一个预定的“生成多项式”进行除法运算。除法的余数(也叫 CRC 校验码)就是要附加到数据中的校验值。

  • 优点:鲁棒性高,错误检测能力强
  • 缺点:实现复杂,计算成本高

CRC 被广泛应用于通信系统(如以太网、硬盘、CD/DVD)以及文件压缩和存储,例如在磁带存储中检测传输错误,或在互联网传输过程中检测数据完整性。

MAC

MAC 是一种结合了加密和哈希的检测方法,除了用于验证数据的完整性外,还能验证数据的身份(即消息的真实性)。MAC 使用一个密钥和一个哈希算法(如HMAC)对消息进行加密处理,生成一个短小的“验证码”。只有知道密钥的双方才能生成和验证该验证码。但是,MAC 无法检测任何内容上的错误!

  • 优点:不仅保证数据未被篡改,还能够验证数据的来源,抗篡改性强
  • 缺点:计算成本较高,依赖于同一个共享密钥,无法检测到内容的错误

MAC 被广泛应用于加密通信协议(如SSL/TLS)、身份验证数字签名支付系统中,确保数据的安全性和完整性。

有限状态机(Finite State Machines)

有限状态机

有限状态机是一个状态转换模型,它包括:

  • 状态(State):系统可能处于的不同阶段。
  • 事件(Event):系统状态转移的触发因素,可以是输入的外部信号或某些条件的变化。
  • 状态转移(Transition):从一个状态到另一个状态的变化过程。
  • 动作(Action):在状态转移时执行的操作,如发送数据包、接收数据等。

TCP 有限状态机

流量控制(Flow Control)

问题在于,如果主机 A 以每秒 500,000 个数据包的速度发送,但是 主机 B 只能每秒接收 200,000 个数据包,这就会导致多余的数据包被丢弃。

如今大多数协议中使用两种方法

  • Stop and Wait
  • Sliding Window

停止-等待(Stop and Wait)

  • 发送方一次只发送一个数据包
  • 每当接收到数据时,接收方发送确认信息(ACK)
  • 发送方接收到确认信息时发送下一个数据包
  • 若超时为收到确认信息,发送方重新发送数据
  • 使用一位计数器来检测是否是重复的数据

停止-等待协议的有限状态机

滑动窗口(Sliding Window)

每个数据段都有一个序列号(SeqNo),用于确保数据包被正确接收、乱序回复、丢包检测等

发送方的工作机制

发送方的工作机制

  1. 维护以下三个变量:

    • 发送窗口大小(Send Window Size, SWS):
      表示当前允许发送但尚未收到确认的最大数据段数,发送窗口的大小决定了 TCP 连接的流量控制能力

    • 最后一个已确认的数据段(Last Acknowledgment Received, LAR):
      这是发送方收到的 ACK 号,即 所有比它小的序列号的数据都已经成功到达接收方

    • 最后一个已发送的数据段(Last Segment Sent, LSS):
      这是当前发送方已经发送的 最大序列号

  2. 维护不等式:LSSLARSWS

  3. 接收新的 ACK 后,推进 LAR,腾出窗口空间,发送新数据

  4. 使用缓存存储未确认的数据,提高数据传输效率

接收方的工作机制

接收方的工作机制

  1. 维护三个变量
    • 接收窗口大小(Receive Window Size,RWS)
    • 最大可接受的序列号(Last Acceptable Segment,LAS)
    • 最后一个成功接收并按序存储的段(Last Segment Received,LSR)
  2. 维护不等式:LASLSRRWS
  3. 发送 ACK:接收方使用 累积确认(Cumulative ACKs),即只确认到最后一个连续的段,比如接收到 1, 2, 3, 5 则会发送 ACK 4(TCP ACK 指的是 “下一个期望的数据”,即 ACK = 4 表示 “请发送 4”)

可靠传输(Reliable Connection)

重传策略(Retransmission Strategies)

针对滑动窗口的重传策略如下

发送方发送数据时,启动一个定时器,若 ACK 超时,则会重传数据

重传策略有两种,回退重传选择重传

回退重传

重传当前窗口的所有数据

  • 优点:实现简单,适合高丢包率的环境(当大量数据丢失时,恢复速度更快)
  • 缺点:浪费带宽,不适合高吞吐量的环境

选择重传

只重传 ACK 超时的数据包

  • 优点:提高带宽利用率,更适应网络抖动
  • 缺点:接收端复杂度更高,需要额外的缓冲区

TCP 连接和断开(TCP Setup and Teardown)

三次握手

步骤 客户端 © 服务器 (S) 关键字段 说明
SYN SEQ=X - SYN=1, ACK=0 客户端请求连接
SYN-ACK - SEQ=Y, ACK=X+1 SYN=1, ACK=1 服务器确认并发送 SYN
ACK SEQ=X+1, ACK=Y+1 - ACK=1 客户端确认,连接建立

TCP 还支持另一种连接方式,称为 同时打开(Simultaneous Open)

两方同时发送 SYN 然后一同发送 SYN+ACK,这需要四条消息而不是三次握手的三条

四次挥手

步骤 发送方 接收方 关键标志位 作用
FIN 客户端 → 服务器 FIN=1, ACK=1 客户端请求断开
ACK 服务器 → 客户端 ACK=1 服务器确认 FIN
FIN 服务器 → 客户端 FIN=1, ACK=1 服务器也准备断开
ACK 客户端 → 服务器 ACK=1 客户端确认 FIN,进入 TIME_WAIT

关于 TIME_WAIT

在客户端发送 最后一个 ACK 之后,会进入 TIME_WAIT 状态,持续 2 倍最大报文段生存时间(2MSL, Maximum Segment Lifetime)。这样做的目的如下:

  1. 确保服务器收到了 ACK:
    如果最后的 ACK 丢失,服务器会重新发送 FIN,客户端可以重新 ACK。

  2. 防止旧连接影响新连接:
    旧的 TCP 连接可能会有延迟的数据包,TIME_WAIT 确保它们都被丢弃。

总结

在计算机网络中,传输层协议的设计至关重要,它直接影响数据在网络中的传输方式与可靠性。TCP、UDP 和 ICMP 各自提供了不同的通信模型,适用于不同的应用需求。

  • TCP 服务模型(TCP Service Model) 采用连接导向的通信方式,提供可靠的数据传输、流量控制和拥塞控制,确保数据的顺序性和完整性。它适用于对数据可靠性要求较高的应用,如网页浏览(HTTP/HTTPS)和文件传输(FTP)。
  • UDP 服务模型(UDP Service Model) 采用无连接的通信方式,不保证数据可靠性、顺序性和完整性,但具有低延迟、高吞吐的优点,适用于实时音视频通信(如 VoIP、在线游戏)等应用。
  • ICMP 服务模型(ICMP Service Model) 主要用于网络诊断和错误报告,帮助主机和路由器报告网络问题,如 pingtraceroute

在传输过程中,端到端原则(End-to-End Principle)强调应在通信的终端系统(如应用层)实现可靠性,而非依赖网络中的中间节点。

错误检测(Error Detection)机制(如 TCP 校验和、UDP 校验和和 ICMP 误码报告)在数据传输中起到了关键作用,确保数据完整性。

有限状态机(Finite State Machines, FSM)是 TCP 连接管理的核心,定义了从连接建立(三次握手)到连接终止(四次挥手)的完整状态转换过程。流量控制(Flow Control)机制,如 TCP 的滑动窗口协议,确保发送方不会发送超过接收方缓存能力的数据,防止接收端溢出。

可靠传输(Reliable Connection)是 TCP 的核心特性之一,它通过 ACK 机制、超时重传、滑动窗口、拥塞控制(如 AIMD、慢启动) 来确保数据的正确、完整、有序传输。在不同网络条件下,TCP 还能动态调整其发送策略,以提高传输效率和网络利用率。

综合来看,计算机网络协议的设计在可靠性、性能和复杂性之间做出了权衡,不同的应用场景需要选择合适的传输方式,以实现最优的通信效果。