Linux 使用 Protocol Buffers 在 TCP 中需要自己设计协议头以解决 “粘包” 问题吗?

qichunren · 2018年08月14日 · 最后由 yfractal 回复于 2018年08月17日 · 7905 次阅读

由于 TCP 是流式的,我发送数据时,使用 Protocol Buffers 序列化消息后,需要额外将序列化的消息放进自己设计的数据包中吗?还是可以直接发送给接收方?

想知道 Protocol Buffers 本身是否已经支持这一点,即接收方收到数据放入数据缓冲区后,直接反序列化即可解析出消息实体?

不用再包一遍了吧, SDK 会帮你搞定

“粘包” 是一个不存在的概念。提出这个概念的人肯定没有理解 TCP。send 不表示把数据作为一个包发出去了,receive 也不表示接收到的一定是一个包。开发者需要自己定义包格式以及解析规则,正好 Protocol Buffers 把这些事都做好了,直接用就好了。

我见过有人为了解决所谓的 “粘包” 问题,每次 send 之后都来一次 sleep,以此保证另一端 receive 的时候不会受到多于一个包的数据,显然这是一种非常蠢的做法。之所以用这么蠢的做法,是因为脑子里臆想了一个更蠢的 “粘包” 概念。

本身没有,可以 2 字节表示包长

不明白 protobuf 跟 TCP 有啥关系,直接 encode 成 binary 发过去后,对方再 decode 就好了

tony612 回复

erlang gen_tcp 有 {packet, N},其它语言要自己搞吧

lidashuang 回复

@lidashuang 两个字节也不行吧,还得加自己构建一个包头和包尾。

@tony612 消息 encode 之后,对方收到的消息是流式的,也就是前后没有边界的,需要定义一个规则才能确定数据包的位置的。

qichunren 回复

用 Protocol Buffer 就上 gRPC https://grpc.io/

Protobuf 确实跟 TCP 没啥关系啊,protobuf 只是一种二进制消息打包方式,你 TCP 怎么分包跟他没啥关系。

最简单的办法就是留一个定长的头来存储后面消息的长度就好了

要具体看协议了。比如直接读 16 位,有哪几位是长度啥的。 既然用 protobuf 了,为啥不直接 grpc 呢?

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册