报文接收处理
2025/8/31大约 2 分钟
报文接收处理
一次接收不同类型的多个包(TCP粘包)
测试
准备数据:
模拟被控站:建立连接后将以下数据包一次性发送给控制站
- startdt con:启动数据传输确认
- I(0,0):包含两个M_ME_NB_1数据
- I(1,0):包含1个M_ME_NC_1 数据
// startdt con
0000 68 04 0b 00 00 00
//I(0,0)
0000 68 16 00 00 00 00
//M_ME_NB_1
0000 0b 02 01 00 01 00 6e 00 00 00 00 00 6f 00 00 00
0010 00 00
//I(1,0)
0000 68 12 02 00 00 00
//M_ME_NC_1
0000 0d 01 01 00 01 00 78 00 00 25 06 49 40 00
综合:
68 04 0b 00 00 00 68 16 00 00 00 00 0b 02 01 00 01 00 6e 00 00 00 00 00 6f 00 00 00 00 00 68 12 02 00 00 00 0d 01 01 00 01 00 78 00 00 25 06 49 40 00使用网络调试助手:
设置为TCP server,端口号设置为2404
启动client,连接到server
连接建立成功后回复数据包
结果:
msgSize: 6
RCVD:
" 68 4 b 0 0 0"
msgSize: 24
RCVD:
" 68 16 0 0 0 0 b 2 1 0 1 0 6e 0 0 0 0 0 6f 0 0 0 0 0"
msgSize: 20
RCVD:
" 68 12 2 0 0 0 d 1 1 0 1 0 78 0 0 25 6 49 40 0"解析时数据包被拆分为3包,长度分别为6,24,20. 和单个帧发送的数据对应。
获取到一帧报文
APCI中包含了报文起始标志(0x68)以及帧长度(不包含起始字节 以及 长度本身)。
首先发送方保证没有发送额外的包含了0x68的非有效帧的内容,TCP 保证了数据不会出错。
处理逻辑:
- 找到起始字节;
- 获取长度
- 获取整帧数据
实现:
static int
receiveMessage(CS104_Connection self);| 返回值 | 含义 |
|---|---|
| -1 | 读取socket出错 |
| 0 | socket 中没有数据 |
| >0 | 读取到完整的一帧,数据存储在了buffer |
| bufPos的值 | 含义 |
|---|---|
| 0 | 没有找到帧起始字节 |
| 1 | 已找到帧头 |
| >1 | 已找到帧头 及 长度 |
| bufPos 表示已读取数据的长度 (也是未读取数据填充buffer的起始位置) |
是否读取到完整一帧的判断:
int remainingLength = length - bufPos + 2;