Netty 解决粘包拆包

While parsing a protocol message, the input ended unexpectedly in the middle of a field. This could mean either that the input has been truncated or that an embedded message misreported its own length.java

出现上述这个问题我以为是您使用protlcol的方式不对;也就是出现了粘包拆包的问题; 上一篇文章介绍了Netty中使用Protobuf的编码解码,下面介绍一下粘包拆包的问题;git

什么是粘包、拆包?github

在基于流的传输里好比TCP/IP,接收到的数据会先被存储到一个socket接收缓冲里。不幸的是,基于流的传输并非一个数据包队列,而是一个字节队列。即便你发送了2个独立的数据包,操做系统也不会做为2个消息处理而仅仅是做为一连串的字节而言。 所以这是不能保证你远程写入的数据就会准确地读取。举个例子,让咱们假设操做系统的TCP/TP协议栈已经接收了3个数据包:编程

在这里插入图片描述

因为基于流传输的协议的这种普通的性质,在你的应用程序里读取数据的时候会有很高的可能性被分红下面的片断多线程

image.png

所以,一个接收方无论他是客户端仍是服务端,都应该把接收到的数据整理成一个或者多个更有意思而且可以让程序的业务逻辑更好理解的数据。在上面的例子中,接收到的数据应该被构形成下面的格式:并发

在这里插入图片描述

解决方法由以下几种:框架

一、消息定长,报文大小固定长度,例如每一个报文的长度固定为200字节,若是不够空位补空格;socket

二、包尾添加特殊分隔符,例如每条报文结束都添加回车换行符(例如FTP协议)或者指定特殊字符做为报文分隔符,接收方经过特殊分隔符切分报文区分;函数

三、将消息分为消息头和消息体,消息头中包含表示信息的总长度(或者消息体长度)的字段;工具

Netty提供了多个解码器,能够进行分包的操做,分别是:

LineBasedFrameDecoder (利用换行符解决)

DelimiterBasedFrameDecoder(添加特殊分隔符报文来分包)

FixedLengthFrameDecoder(使用定长的报文来分包)

LengthFieldBasedFrameDecoder   
复制代码

这里咱们介绍一下LineBasedFrameDecoder(利用换行符解决)的使用方式:

LineBasedFrameDecoder 解码器使用很是简单,只须要在 pipline 链条上添加便可。

//字符串解析,换行防拆包
.addLast(new LineBasedFrameDecoder(1024))
.addLast(new StringDecoder())
复制代码

构造函数中传入了 1024 是指报的长度最大不超过这个值;

注意,因为 LineBasedFrameDecoder 解码器是经过换行符来判断的,因此在发送时,一条完整的消息须要加上 \n。

例如:

在这里插入图片描述
Protocol 拆、粘包

接下来咱们使用Protocol 来解决,拆、粘包,用Protocol来解决拆、粘包那是至关简单的. 只须要在服务端和客户端加上这两个编解码工具便可:

//拆包解码
.addLast(new ProtobufVarint32FrameDecoder())
.addLast(new ProtobufVarint32LengthFieldPrepender())
复制代码

可是注意一点,添加pipeline链的时候必定要注意顺序(我在写案例的时候遇到的);具体请参考本案例代码;

这个编解码工具能够简单理解为是在消息体中加了一个 32 位长度的整形字段,用于代表当前消息长度。

demo 地址:

当前项目:Netty框架--netty编码解码(项目中proto包下)

多线程并发编程(项目中thread包下)

BIO编程(项目中bio包下)

NIO编程(项目中nio包下)

自定义RPC(项目中rpc包下)

欢迎给个小星星鼓励一下(记得Star哦,害羞脸).... 我只是给代码注入灵魂

相关文章
相关标签/搜索