解决方案:
方案一:
设置定⻓消息,服务端每次读取既定⻓度的内容作为⼀条完整消息(固定缓冲区大小);
方式二: 使⽤⾃定义协议+编解码器(封装请求协议);
方案三: 设置消息边界,服务端从⽹络流中按消息编辑分离出消息内容(特殊字符结尾,按行读取)。
优缺点:
方案一:
从以上代码可以看出,虽然这种方式可以解决粘包和拆包的问题,但这种固定缓冲区大小的方式增加了不必要的数据传输;当这种方式当发送的数据比较小时会使用空字符来弥补,所以这种方式就大大的增加了网络传输的负担,所以它也不是最佳的解决方案。
方案二: 实现较为复杂,更多情况下使用该种实现;Dubbo实现自定义的传输协议,使用Netty来实现可降低编码复杂程度,netty框架对于粘包有专门encoder和decoder接口来处理。
方案三: 特殊字符的方案其实是最不可取的;TCP是面向流的;所以应该认为TCP传输的是字节流,任何一个字节都可能被传输;在这种情况下,特殊字符也不特殊了,没法和正常数据区分。
Netty中的解码器:
- 消息长度固定,累计读取到消息长度总和为定长Len的报文之后即认为是读取到了一个完整的消息。计数器归位,重新读取。FixedLengthFrameDecoder
- 将回车换行符作为消息结束符。LineBasedframeDecoder
- 将特殊的分隔符作为消息分隔符,回车换行符是他的一种。DelimiterBasedFrameDecoder
- 通过在消息头定义长度字段来标识消息总长度。