通过设置报文头固定长度解决mina断包粘包的问题
最近项目中遇到了一个基于mina的断包粘包问题,下面分享下解决方案。
~~~~~~ 在mina中,一般的应用场景使用TextLineDecoder的Decode和Encode就够了(TextLine的默认分割符是\r\n,也可以通过new TextLineDecoder(charset,decodingDelimiter)方法指定分隔符),但默认解码器每次读取缓冲的数据是有限制的,即ReadBufferSize的大小,默认是2048个字节,当数据包比较大时将被分成多次读取,造成断包。虽然可以通过acceptor.getSessionConfig().setReadBufferSize(newsize)这种方式来增加默认容量,但容易造成空间浪费,肯定也会降低数据的处理效率。所以,当我们接收的数据的大小不是很固定,且容易偏大的时候,默认的TextLine就不适合了。这时我们在解析之前就需要判断数据包是否完整,这样处理起来就会非常麻烦。
~~~~~~ 幸好mina中提供了CumulativeProtocolDecoder类,从名字上可以看出累积性的协议解码器,也就是说只要有数据发送过来,这个类就会去读取数据,然后累积到内部的IoBuffer 缓冲区,但是具体的拆包(把累积到缓冲区的数据解码为JAVA 对象)交由子类的doDecode()方法完成。通过阅读源码,我们可以发现CumulativeProtocolDecoder就是在decode()方法内反复地调用暴露给子类实现的doDecode()方法。
~~~~~~ CumulativeProtocolDecoder的具体执行过程如下所示:
~~~~~~ (1)你的doDecode()方法返回true时