1.什么是TCP粘包与拆包

首先TCP是一个"流"协议,犹如河中水一样连成一片,没有严格的分界线。当我们在发送数据的时候就会出现多发送与少发送问题,也就是TCP粘包与拆包。得不到我们想要的效果。

所谓粘包:当你把A,B两个数据从甲发送到乙,本想A与B单独发送,但是你却把AB一起发送了,此时AB粘在一起,就是粘包了

所谓拆包: 如果发送数据的时候,你把A、B拆成了几份发,就是拆包了。当然数据不是你主动拆的,是TCP流自动拆的

2.TCP粘包与拆包产生原因

1.进行了MSS大小的TCP分段
2.以太网帧的plyload大与MTU进行了IP分片
3.应用程序write写入的字节大小大于套接口发送的缓冲区大小

3.解决方法

1.消息定长,比如把报文消息固定为500字节,不够用空格补位

2.在包尾增加回车换行符进行分割,例如FTP协议

3.将消息分为消息头和消息体,消息头中包含表示消息总长度的字段

4.更复杂的应用层协议

4.Netty解决方案

1、LineBasedFrameDecoder (换行)
给pipline 加上这俩个类,每次发送消息的时候加入换行符
原理就是:
它依次遍历ByteBuf中的可读字节,判断是否有\n或\r\n,如果有,就以此为结束位置,从可读索引到结束位置区间的字节组成一行。它是以换行符为结束标志的解码器,支持携带结束符或者不携带结束符两种解码方式,同时支持配置单行的最大长度。
2、FixedLengthFrameDecoder(使用定长的报文来分包)
FixedLengthFrameDecoder是固定长度解码器,它能够按照指定的长度对消息进行自动解码,开发者不需要考虑TCP的粘包/拆包等问题,非常实用。
利用FixedLengthFrameDecoder解码器,无论一次接收到多少数据报,它都会按照构造函数中设置的固定长度进行解码,如果是半包消息,FixLengthFrameDecoder会缓存半包消息并等待下个包到达后进行拼包,直到读取到一个完整的包。
HTTP请求消息可以一次性接收完成,此时ChannelHandler的channelReadComplete方法会被调用一次,但当一个整包消息经过多次读取才能完成解码时,channelReadComplete方法就会被调用多次。channelRead是只有在消息被解码成功后才会调用channelRead方法
3、DelimiterBasedFrameDecoder(添加特殊分隔符报文来分包)
DelimiterBasedFrameDecoder是分隔符解码器,用户可以指定消息结束的分隔符,它可以自动完成以分隔符作为码流结束标识的消息的解码。
回车换行解码器实际上是一种特殊的DelimiterBasedFrameDecoder解码器。
4、LengthFieldBasedFrameDecoder (自定义解码器跟编码器)
LengthFieldBasedFrameDecoder,一般包含了消息头(head)、消息体(body):消息头是固定的长度,一般有有以下信息 -> 是否压缩(zip)、消息类型(type or cmdid)、消息体长度(body length);消息体长度不是固定的,其大小由消息头记载,一般记载业务交互信息。