网闸连接器 UDP 传输协议规范
版本: 1.0
概述
网闸连接器在入口代理和出口代理组件之间,基于 UDP 使用一个自定义的、轻量级的应用层协议。该协议旨在通过将大型、不透明的二进制数据块分割成更小的 UDP 数据包,并在接收端重新组装它们,从而可靠地跨网闸传输这些数据。
该协议提供以下关键特性:
- 消息分片与重组:允许传输大于标准 UDP 载荷大小的数据块。
- 丢包检测:使用序列号系统来检测丢失的数据包。
- 连接生命周期管理:包含用于启动、关闭和心跳维持的特殊消息类型。
包结构
在传输组件之间交换的每个 UDP 数据包都遵循一个固定的头部结构,其后跟一个可变长度的载荷。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Type | Sequence Number |
| | (LSB, 24 bits) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Sequence Number| Payload Length | Remaining Pkts|
| (MSB, 8 bits) | (Little-Endian) | (LSB) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Remaining Pkts| |
| (MSB) | (Padding) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+头部字段
头部大小固定为 9 字节。
消息类型 (Message Type) (1 字节)
- 一个 8 位无符号整数,定义了数据包的用途。详见消息类型。
序列号 (Sequence Number) (4 字节)
- 一个 32 位无符号整数,采用小端序 (Little-Endian) 格式。
- 每发送一个数据包,该数字加一。
- 接收方用它来检测丢包。序列号
0是一个特例,当乱序接收时(例如,在StartUp消息之后),不表示丢包。
载荷长度 (Payload Length) (2 字节)
- 一个 16 位无符号整数,采用小端序 (Little-Endian) 格式。
- 指定当前数据包中
Payload字段的大小(以字节为单位)。 - 对于
Data和DataFirst数据包,该值通常是最大载荷大小 (MAX_PAYLOAD_SIZE_BYTES),但分片消息的最后一个数据包可能更小。
剩余包数 (Remaining Packets) (2 字节)
- 一个 16 位无符号整数,采用小端序 (Little-Endian) 格式。
- 指示还需接收多少个数据包才能完成当前数据块的传输。
- 对于
DataFirst数据包,此值表示该数据块后续数据包的总数。 - 对于
Data数据包,此值随每个接收到的数据包而递减。 - 当此值为
0时,表示当前数据包是该数据块的最后一个包。
载荷 (Payload)
- 载荷 (可变大小)
- 原始数据块的原始二进制数据段。
- 此字段的大小由头部中的
Payload Length字段定义。
消息类型
Message Type 字段决定了接收方如何处理数据包。
| 值 | 名称 | 描述 |
|---|---|---|
0 | DataFirst | 标记一个新数据块的第一个数据包。接收方从 WaitingForFirstData 状态转换到 WaitingForData 状态,并使用 Remaining Packets 字段来了解还需要期望多少个数据包。 |
1 | Data | 一个分片数据块的后续数据包。接收方收集这些数据包,直到 Remaining Packets 为零,然后重组完整的块。 |
2 | StartUp | 发送方初始化时发送的控制消息。接收到后,接收方将其期望的序列号重置为 0,并返回到 WaitingForFirstData 状态,丢弃任何部分接收的数据。 |
3 | HeartBeat | 一个心跳维持消息。接收方记录其接收情况并保持当前状态。它不影响数据处理。 |
4 | Shutdown | 一个控制消息,指示发送方正在关闭。接收到后,接收方将终止其处理循环。 |
状态机与重组逻辑
接收方使用一个状态机来处理数据包的重组。
初始状态:
WaitingForFirstData- 接收方处于空闲状态,等待新的数据传输开始。
- 它只接受
DataFirst、StartUp、HeartBeat或Shutdown数据包。任何Data数据包都将被丢弃。
接收
DataFirst- 当一个
DataFirst数据包到达时,接收方将其载荷存储为新消息的第一部分。 - 如果
Remaining Packets为0,则消息是完整的。载荷被写入输出缓冲区,状态保持为WaitingForFirstData。 - 如果
Remaining Packets大于0,接收方转换到WaitingForData(N)状态,其中N是此消息的总包数 (Remaining Packets+ 1)。
- 当一个
状态:
WaitingForData(N)- 接收方正在为一个分片消息积极收集数据包。
- 它期望
N-1个后续的Data数据包。 - 每个传入的
Data数据包的载荷都根据其在序列中的位置(使用Remaining Packets值计算)存储在中间缓冲区中。 - 如果在此状态下意外收到一个
DataFirst数据包,当前的重组将被中止,部分数据被丢弃,并用这个新包开始一个新的重组过程。
接收最后一个
Data包- 当一个
Remaining Packets等于0的Data数据包到达时,它标志着消息的结束。 - 接收方将中间缓冲区中所有存储的载荷组合成一个单一、连续的字节数组。
- 这个重组后的数据块随后被写入输出
bip_buffer,供下游组件使用。 - 状态机转换回
WaitingForFirstData。
- 当一个
丢包处理
- 在每收到一个数据包时,接收方都会将其
Sequence Number与其期望的序列号进行比较。 - 如果
incoming > expected,接收方检测到一个或多个数据包已丢失。 - 当检测到丢包时,接收方将中止当前消息的重组,丢弃该消息的所有已缓冲数据,并将其状态重置为
WaitingForFirstData。这确保了损坏或不完整的数据块不会被转发。
- 在每收到一个数据包时,接收方都会将其