4、协议基础:基于TCP/IP的通信协议栈与报文结构
各位好,我是老轨。今天咱们聊聊PIS系统和列车控制系统之间通信的“底层语言”——TCP/IP协议栈和报文结构。这部分内容,说白了就是两个系统之间怎么“说话”、怎么“听懂对方”。
我在现场调试的时候,遇到过不少因为协议理解不透彻导致的通信故障。你想想看,两个系统明明都通电了,网线也插好了,可就是“鸡同鸭讲”。嗯,问题多半出在协议栈的某一层上。
4.1 为什么选择TCP/IP?
我个人习惯,在轨道交通信号系统里,首选就是TCP/IP。为什么?
- 可靠性高:TCP的确认重传机制,能保证报文不丢、不乱序。这在信号系统里是底线。
- 跨平台性好:无论是Windows、Linux还是嵌入式系统,TCP/IP都是标配。
- 分层清晰:每一层各司其职,出了问题好排查。
核心要点:PIS与TCMS(列车控制管理系统)之间的通信,我建议统一采用TCP协议,端口号建议固定为5000-5005区间,避免冲突。
4.2 协议栈的四层模型
咱们不搞那些花里胡哨的七层模型,轨道交通现场,四层模型就够用了。我给大家拆开讲讲:
| 层级 | 名称 | 作用 | 现场常见问题 |
|---|---|---|---|
| 第4层 | 应用层 | 定义报文格式、业务逻辑 | 报文解析错误、字段对齐问题 |
| 第3层 | 传输层 | TCP/UDP端口管理、可靠传输 | 端口被占用、连接超时 |
| 第2层 | 网络层 | IP地址路由、寻址 | IP冲突、子网掩码不匹配 |
| 第1层 | 链路层 | MAC地址、物理介质访问 | 网线接触不良、交换机端口故障 |
我的经验:排查通信故障时,从第1层往上查。先看网口灯亮不亮,再ping IP,最后抓包看应用层。这个顺序能省你半天时间。
4.3 报文结构设计
好了,协议栈选好了,接下来就是报文长什么样。我在项目中用过不少报文格式,最后沉淀下来一套比较通用的结构,分享给大家:
| 帧头(2字节) | 长度(2字节) | 类型(1字节) | 序列号(2字节) | 时间戳(4字节) | 数据域(N字节) | 校验(2字节) | 帧尾(2字节) |
| 0xAA55 | N+13 | 0x01 | 0x0001 | Unix时间戳 | 实际数据 | CRC16 | 0x55AA |
每个字段的含义,我挨个说一下:
- 帧头(0xAA55):固定值,用于同步。我曾经遇到过一帧数据中间断了,靠这个帧头重新找到起始位置。
- 长度字段:从类型字段开始到校验字段结束的总字节数。注意,这个长度不包含帧头和帧尾。
- 类型字段:区分不同业务。比如0x01是状态上报,0x02是控制指令。
- 序列号:每发一帧加1,用于去重和排序。嗯,这个在丢包重传时特别有用。
- 时间戳:Unix时间戳,精确到秒。PIS系统需要根据这个时间戳做信息同步。
- 数据域:真正的业务数据,长度可变。
- 校验(CRC16):对整个报文(从帧头到数据域)做循环冗余校验。我曾经因为校验算法写错,排查了整整两天……
- 帧尾(0x55AA):固定值,表示报文结束。
避坑指南:我曾经见过一个项目,帧头和帧尾用了相同的值(比如都是0xAA55)。结果接收方在解析时,把帧尾误判成了帧头,整个报文解析全乱套了。记住:帧头和帧尾一定要不同!
4.4 实际通信流程
光有报文结构还不够,还得知道怎么“握手”。我给大家画个简单的流程:
- 建立连接:PIS系统作为客户端,主动向TCMS的5000端口发起TCP连接。
- 发送心跳:连接建立后,每1秒发送一次心跳报文(类型0x00),保持连接活跃。
- 数据交互:TCMS收到心跳后,回复状态报文(类型0x01)。PIS根据状态报文,决定是否下发控制指令。
- 断开连接:列车断电或系统关闭时,主动发送FIN包断开连接。
关键点:心跳超时时间我建议设为3秒。超过3秒没收到心跳,就认为连接断了,需要重新建立。这个值是我在多个项目里试出来的,太短容易误判,太长反应太慢。
4.5 数据域的具体定义
数据域里装什么?以PIS系统最常用的“列车到站信息”为例:
| 车站ID(2字节) | 到站时间(4字节) | 开门方向(1字节) | 预留(1字节) |
| 0x0012 | 0x5F4E3D2C | 0x01 | 0x00 |
- 车站ID:0x0012表示第18号车站(从0开始编号)。
- 到站时间:Unix时间戳,精确到秒。
- 开门方向:0x01表示左侧开门,0x02表示右侧开门。
- 预留字段:为了后续扩展,先填0x00。
我个人习惯,所有多字节字段都采用大端序(Big-Endian)。为什么?因为网络字节序就是大端序,省得来回转换。你想想看,要是PIS用大端,TCMS用小端,那解析出来的数据全是乱的。
小技巧:在开发阶段,可以用Wireshark抓包验证报文。我每次写完协议解析代码,第一件事就是抓包看原始字节流,跟设计文档逐字节比对。这一步能发现90%的隐藏bug。
4.6 总结一下
好了,这一章的内容就这些。TCP/IP协议栈是PIS和TCMS通信的骨架,报文结构是血肉。记住三点:
- 协议栈选TCP,端口固定5000-5005
- 报文结构要包含帧头、长度、类型、序列号、时间戳、数据、校验、帧尾
- 多字节字段统一用大端序
下一章,咱们聊聊具体的接口定义和信号映射。到时候我会拿一个实际项目的接口文档来拆解,保证干货满满。