基于 Netty 的通信组件如何解决粘包拆包问题

拆包粘包的场景分析

粘包和拆包的场景主要有下图几种:

客户端首先和服务端建立 TCP 连接,然后客户端向服务端发送请求,我们假设客户端发送的请求就是手写 RPC 项目的 NettyRpcRequest, 我们假设一个 NettyRpcRequest 的字节大小为128,客户端向服务端发送了三个数据包:

  1. 数据包1:粘包现象。数据包1包涵两个完整的 rpcRequest 字节数组包括 rpcRequest0 和 rpcRequest1。
  2. 数据包2:拆包现象。数据包2只包涵 rpcRequest2 从0到65的字节,也就是说只有部分的 rpcRequest2 的数据。
  3. 数据包3:同时具有粘包和拆包现象。数据包3包涵了 rpcRequest2 从66到127的字节,同时包涵了全部的 rpcRequest3 的字节。

而服务端收到每一个数据包的时候是无法判断数据包内的情况的,也就是说TCP 协议是面向字节流的而不是语义。我们再看一个代码例子,这样会更加有说服力。

拆包粘包的例子

配套的源码源代码地址:github.com/sean417/net… 的 netty-rpc 模块。

下面的 sticky 包做了一个模拟粘包的例子:

首先,我们看看客户端的代码:

客户端会发送500个带有换行符的字节数组请求 pingBytes,每个 pingBytes 的末尾都会有一个换行符。

然后,再看一下 服务端的接收请求的代码:

分别执行服务端启动类 NettyStickyPacketServer 和 客户端启动类 NettyStickyPacketClient。 服务端输出结果:

大家可以看出来既有拆包的情况也有粘包的情况。拆包和粘包对接收方来说必须要解决的问题,因为接收方是要把字节流反序列化为业务对象的,而业务对象是由语义的,需要把没有语义的字节流转换为有语义的业务对象。那么我们应该怎么处理呢?

粘包拆包的解决方案

主要有两种解决方案:

一个请求由请求长度和请求体组成

反序列化类 RpcDecoder:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值