2021SC@SDUSC
前言
前面已经介绍过粘包与拆包问题:
粘包拆包问题
粘包和拆包实例演示
下面介绍一下Netty提供的粘包拆包解决方案
Netty提供了一系列的编解码器来解决 TCP 的粘包、半包问题:
FixedLengthFrameDecoder(基于固定长度的解码器)
LineBasedFrameDecoder (基于行分隔符的解码器)
DelimiterBasedFrameDecoder (基于自定义分割符的解码器)
LengthFieldBasedFrameDecoder(基于长度字段的解码器)
FixedLengthFrameDecoder
FixedLengthFrameDecoder常用于使用固定长度的粘包和拆包场景。
解码器每次读取固定长度的消息,在使用这个解码器时需要在构造函数中指定每个消息的长度frameLength,解码器每当读到frameLength长度的字节时,就解码出一个数据对象
需要注意的是,如果当前读取到的消息不足指定长度,那么就会等待下一个消息到达后进行补足,例如发送方发送了四次数据:A、BC、DEFG、HI,指定frameLength=3,那么解码的结果就是ABC、DEF、GHI
或者我们可以自己来编写编码器,编码时只需要将不足指定长度的部分进行补全即可
下面演示一下如何使用FixedLengthFrameDecoder来进行粘包和拆包处理:
服务端
public class MyServer {
public void bind(int port) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// 将FixedLengthFrameDecoder添加到pipeline中,指定长度为10
ch.pipeline().addLast(new FixedLengthFrameDecoder(10));
// 将解码得到的数据转码为字符串
ch.