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

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

由于 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 呢?

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