为什么在Netty里说这个呢?
因为粘包和拆包与Netty有关,而且Netty有合适的解决办法
Tcp粘包/拆包现象
如果用Netty传输100次相同的数据给Server端,可以输出一下传过来的数据看看
ChannelHandlerContext.channel().writeAndFlush(ByteBuf ); //ByteBuf 为Netty的一个字节容器
图片Copy别人的,应该能看的差不多
这里面出现了三种形式,
- 一种是正好传输一行的数据的是一个完整的我们想传过去的数据
- 一种是一行有很多重复的完整的传输的数据(为了方便,一行完整的数据重复发送了100次)
- 一种是一行虽然有重复的,但是也有不完整的,缺少的部分不是在上一行就是在下一行
上面这三种情况中第二种叫粘包,很多数据粘在一起,第三种叫半包,数据不完整
原因:Netty是应用层的,但是传输数据还是TCP协议,相当于Netty 的数据转成TCP中的字节流再发送,接收方用TCP协议接收,再通过Netty转成ByteBuf,也就是转成Netty协议的数据
到现在也就讲了粘包,那拆包呢?
别慌,其实粘包主要是发送方也就是客户端进行的操作,把多条数据粘成一条发送过去,而接收方也就是服务方主要就是根据应用协议把发送过来粘着的数据拆开,称之为拆包。
上面那个图片是没有经过拆包后的显示也就是原生态的粘包发送过来的样子,而Netty 对于拆包已经有很多类型的拆包器了,当然不用Netty的拆包器也行,就需要自己去判别是否是一个完整的包等等,不过挺麻烦的,还要不停的从TCP缓冲区读取数据等等,既然已经有封装好的,我们为什么不用呢?
选好拆包器后,在代码中client段和server端将拆包器加入到chanelPipeline之中就好了(一个在粘之前做好约定,一个在拆之前根据约定拆):
客户端:
ch.pipeline().addLast(new FixedLengthFrameDecoder(31));
服务端:
ch.pipeline().addLast(new FixedLengthFrameDecoder(31));
看到上面两个程序中addLast 字面意思就是在每一个完整的数据后面都加一个标识符,代表我前面的31长度的是一个完整的数据,当然如果没有31个它就会碰到前一个的标识符,就停下来,
就是这样这样就顺眼多了