3. 网络传输与协议基础
交易所行情系统对“快”和“稳”的要求远高于普通互联网应用。理解行情协议之前,必须先理解它跑在什么样的网络与编码基础上。本节围绕传输层选择、组播分发、二进制与文本编码、字节序、对齐填充,以及常见行情传输架构展开,帮助你建立从网线到内存的完整链路认知。
一、核心原理:传输层与分发方式决定行情性格
行情传输的第一层选择是 TCP 还是 UDP。TCP 提供可靠、有序、面向连接的字节流,适合逐笔委托、成交回报、快照补全等不能丢数据的场景;UDP 无连接、不保证到达与顺序,但延迟低、开销小,适合高频快照、组播行情。交易所常采用“UDP 组播为主 + TCP 补包/快照恢复”的混合模式。
组播(Multicast)是行情分发的关键机制。发送端只需向一个组播组地址发送一份数据,网络设备按需复制到多个接收者,避免单播模式下服务器为每个客户端单独发送。常见组播地址范围为 224.0.0.0~239.255.255.255,配合 IGMP 管理加入与离开。组播的代价是不可靠:交换机、网卡、内核缓冲区都可能丢包,因此协议层必须设计序列号与重传/补包机制。
二、二进制协议与文本协议:编码方式对比
文本协议(如 FIX、JSON、CSV)可读性强、调试方便,但解析需要字符串扫描、类型转换,字段名重复传输,带宽与 CPU 开销大。二进制协议(如 STEP、FAST、SBE、自定义 TLV)以固定或变长字段直接映射内存,解析快、体积小,是交易所行情的主流选择。
二进制协议中,字节序(Endianness)决定多字节整数在内存中的排列。大端(Big-Endian)高位字节在前,网络字节序即大端;小端(Little-Endian)低位字节在前,x86 与 ARM 常见。协议文档必须明确字节序,否则价格、数量字段会解析成完全错误的值。
对齐与填充(Alignment & Padding)是另一个易错点。CPU 访问未对齐内存可能降速甚至异常,编译器会按字段自然边界插入填充字节。若协议结构体直接按内存布局发送,必须显式控制对齐,否则发送端与接收端结构体大小不一致,字段错位。
| 维度 | 文本协议 | 二进制协议 |
|---|---|---|
| 可读性 | 高,可直接查看日志 | 低,需工具解码 |
| 带宽开销 | 大,字段名与分隔符重复 | 小,字段紧凑 |
| 解析速度 | 慢,需扫描与转换 | 快,可直接映射 |
| 扩展性 | 灵活,新增字段容易 | 需版本与长度字段配合 |
| 典型场景 | FIX 会话、管理接口 | 逐笔、快照、组播行情 |
三、方法流程:从网卡到应用的数据解析路径
- 网卡收到组播帧,DMA 写入内核环形缓冲区,触发中断或轮询。
- 内核按 UDP 端口将数据报交给对应 socket,应用通过 recvfrom 读取。
- 应用按协议头解析:魔数、版本、消息类型、序列号、长度字段。
- 按字节序读取价格、数量、时间戳等字段,注意对齐与填充。
- 校验序列号连续性,发现缺口则触发补包或快照恢复。
- 解码后的结构化数据进入行情引擎,供策略与风控消费。
// 大端读取 32 位无符号整数示例
uint32_t read_u32_be(const uint8_t *p) {
return ((uint32_t)p[0] << 24) |
((uint32_t)p[1] << 16) |
((uint32_t)p[2] << 8) |
((uint32_t)p[3]);
}
// 小端读取
uint32_t read_u32_le(const uint8_t *p) {
return ((uint32_t)p[3] << 24) |
((uint32_t)p[2] << 16) |
((uint32_t)p[1] << 8) |
((uint32_t)p[0]);
}
四、案例/场景:组播行情丢包与字节序错位复盘
某量化团队接入交易所组播快照行情,发现偶发价格跳变到极大值。排查发现:协议文档规定价格字段为大端 64 位整数,但代码按小端读取,导致高低字节颠倒。修复后数值恢复正常。另一案例中,接收端序列号出现缺口却未触发补包,原因是补包服务地址配置错误,导致行情引擎持续使用过期快照。这两个案例说明:字节序与序列号校验是行情接入的“生命线”。
五、常见行情传输架构与误区
常见架构包括:交易所组播直发、经行情网关汇聚转发、通过专线或云联网跨地域分发、以及 TCP 快照补全通道。组播适合局域网内多消费者,跨广域网通常转为单播或消息队列。无论哪种架构,都建议在接收端做序列号连续性检查、时间戳延迟监控与丢包统计。
掌握传输层、组播、编码、字节序与对齐这些基础,才能在后续解析快照与逐笔协议时,准确判断字段含义、定位数据异常,并设计出低延迟且可靠的行情接入链路。