现在用golang tcp 进行接收数据。
数据格式:{"xx":"xx"} 标准的josn
但是现在有以下情况出现 出现半包情况
第一次收到数据
{"xx":"xx"}{"xx"
第二次读到
:"xx"}{"xx":"xx"}
以上情况如何进行准确的拆包呢?
(现在已经无法更改数据协议 只能按照这种)
现在用golang tcp 进行接收数据。
数据格式:{"xx":"xx"} 标准的josn
但是现在有以下情况出现 出现半包情况
第一次收到数据
{"xx":"xx"}{"xx"
第二次读到
:"xx"}{"xx":"xx"}
以上情况如何进行准确的拆包呢?
(现在已经无法更改数据协议 只能按照这种)
这是典型的 TCP 粘包问题,你们在设计传输协议之前完全没考虑到这方面。粘包产生的原因主要是以下情况,
处理粘包的方式也有很多,比如,
\n
、\r\n
...当遇到些符号时表示一个包的数据发送完毕,但这种方式效率极低。为什么?因为你读出来要去字符串查找啊。功能码(2字节)+ payload-len(4字节)+payload
其中 payload 的长度取决于 payload-len 的无符号整型数字(大小端问题自己CS两端协商搞定)。
那么这样的协议,如何来读取呢?下面是一段示例程序,
// 1. 读取功能码
ret = read(fd, buf1, 2);
// 2. 根据功能码判断是否合法
...
// 3. 读取 payload-len
ret = read(fd, buf2, 4);
// 4. 如果第三步成功
uint32_t n;
n = ((uint32_t)buf2[1] << 24) | ((uint32_t)buf2[2] << 16) | ((uint32_t)buf2[3] << 8) | ((uint32_t)buf2[4]);
// 5. 读取 payload
ret = read(fd, buf3, n);
按照你们现有无可奈何的机制,我建议在 json 末尾加入特殊符号来达到切割 payload 的效果。
7 回答5.3k 阅读
7 回答3.2k 阅读✓ 已解决
6 回答6.8k 阅读✓ 已解决
4 回答2.3k 阅读
1 回答3.4k 阅读
2 回答935 阅读✓ 已解决
2 回答2.3k 阅读
基于 TCP 的报文啥时候算结束不得你们自己约定么?
比如 HTTP,也是基于 TCP 的,它会在某一行读到
Content-Length
,这个值就是预计的报文总长度,然后读这么多以后就认为所有 TCP 包都收到了,按顺序拼接到一起,就是一个完整的 HTTP 报文。你们在设计报文协议的时候也得有一个机制,好让对方知道啥时候算发完了。
P.S. 主流的基于 TCP 的协议都会不约而同地有头和正文的概念,比如 HTTP、SSH、gRPC、dubbo 等等,你可以思考一下为什么。你这里的只有正文,而没了头。