Netty拆包粘包处理

一、Netty粘包解决方案

当我们使用Netty进行数据传输时,可能会遇到粘包现象,这种现象在单个包大小很小时很常见。但还是有方法来解决这个问题。下面介绍两种最常见的解决方案。

1、FixedLengthFrameDecoder

该解码器固定读取指定消息长度的数据,如果每条消息都是固定长度的,则适合使用此解码器。

2、DelimiterBasedFrameDecoder

该解码器依赖于分隔符对接收到的数据进行拆分。常用的分隔符有”\r\n”、“\n”、“$”等。当每条消息中都包含有分隔符时,适合使用此解码器。

二、Netty自定义粘包拆包

有些情况下,我们的数据并不能依靠固定长度或分隔符区分消息边界,这时候就需要自定义粘包解包。下面给出代码示例。

public class MyDecoder extends MessageToMessageDecoder<ByteBuf> {
   @Override
   protected void decode(ChannelHandlerContext ctx, ByteBuf in,
                         List<Object> out) throws Exception {
       while (in.readableBytes() >= 4) { //判断是否有一个完整的消息
           int length = in.readInt(); //读取消息长度
           if (in.readableBytes() < length) {//不足一个整包,重置读指针
               in.readerIndex(in.readerIndex() - 4);
               return;
           }
           out.add(in.readBytes(length)); //读取完整的数据包
       }
    }
}

以上示例中,我们继承MessageToMessageDecoder类,并重写decode方法,实现自定义解码。在这个例子中,我们读取了前4个字节作为数据包长度,然后根据长度读取完整的数据包。

三、Netty分包粘包处理

1、使用LengthFieldBasedFrameDecoder

该解码器先从ByteBuf中读取指定长度的整型值,该整型值表示实际数据的长度。基于长度解码器,可以解决TCP协议中粘包和分包问题。下面给出代码示例。

public class MyDecoder extends LengthFieldBasedFrameDecoder {

    public MyDecoder() {
        super(ByteOrder.LITTLE_ENDIAN, 1024, 0, 4, 0, 4, true);
//        参数说明:LITTLE_ENDIAN: should length field byte order be littleEndian
//                  1024: maxFrameLength :表示数据帧最大长度
//                  0: lengthFieldOffset :表示数据长度字段值的起始位置,因为我们在发送数据时在数据包的最前面添加了一个4字节的int数据,所以这里为0
//                  4:lengthFieldLength :表示长度字段所占的字节数
//                  0:lengthAdjustment:一个长度调整值,让解码器从第一个字节开始;这里为0
//                  4:initialBytesToStrip:去掉请求头的几个字段长度;这里为4,因为前面我们在请求头加上了4个字节的int数据表示真实数据的长度信息
//                  true:failFast :如果该参数设置为 true,则表示如果帧长度超过长度限制,就会立即抛出一个 TooLongFrameException,而不是等待后续字节到达,这样可以防止太多的资源浪费在非预期包上
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        ByteBuf frame = (ByteBuf) super.decode(ctx, in);
        if (frame == null) {
            return null;
        }
        int realLength = frame.readInt();
        ByteBuf data = frame.slice(frame.readerIndex(), realLength);
        frame.release();
        return data;
    }
}

2、使用MessageToMessageCodec

该编码器先编码,再解码,使用起来相对比较复杂。下面给出代码示例。

public class MyMessageCodec extends MessageToMessageCodec<ByteBuf, Object> {

    @Override
    protected void encode(ChannelHandlerContext ctx, Object msg, List<Object> out) throws Exception {

        ByteBuf byteBuf = ctx.alloc().buffer();
        byteBuf.writeInt(0);  // 占位长度
        byteBuf.writeBytes(msg.toString().getBytes(CharsetUtil.UTF_8));
        byteBuf.setInt(0, byteBuf.readableBytes() - 4); // 记录实际长度
        out.add(byteBuf);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        int length = in.readInt();
        byte[] bytes = new byte[length];
        in.readBytes(bytes);
        out.add(new String(bytes, CharsetUtil.UTF_8));
    }
}

以上代码实现了自定义编解码器。在encode方法中,我们在写入真实数据之前先写入了4个字节的int类型数据,用于记录真实数据的长度信息。在decode方法中,先读取4个字节的int信息,再按照该长度读取真实的数据。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/154762.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-11-16 14:15
下一篇 2024-11-16 14:15

相关推荐

  • gateway io.netty.buffer.poolchunk

    在本文中,我们将深入探讨Netty中的一个基础组件——PoolChunk,它是Netty中ByteBuf的一个关键实现,负责对ByteBuf进行缓存和管理。我们将从多个方面对该组件…

    编程 2025-04-28
  • 同时启动两个netty服务的实现方法

    本文将介绍如何同时启动两个netty服务的具体实现方法。 一、实现思路 为了同时启动两个netty服务,我们需要创建两个不同的Channel,每个Channel都绑定到不同的服务端…

    编程 2025-04-27
  • netty和tomcat的比较

    一、简介 Netty和Tomcat都是Java Web服务器,但它们的设计思想和应用场景不同。 Netty是一个高性能、异步事件驱动的网络通信框架,可以用于实现WebSocket服…

    编程 2025-04-20
  • 深入理解Netty粘包

    一、什么是粘包 网络通信中消息的传输有两个重要的问题,一个是粘包,一个是拆包。 粘包的概念就是发送方发送的多个小数据包被接收方一次性收到,这就像是把多个包“粘”在了一起。 造成粘包…

    编程 2025-04-12
  • Netty in Action:Java网络编程的终极选择

    一、基础概念 Netty是由JBOSS的工程师Norman Maurer和Trustin Lee共同开发的,是一个高性能、异步、事件驱动的网络编程框架。 相比于传统的BIO(Blo…

    编程 2025-01-24
  • 深入探讨Netty ByteBuf

    一、ByteBuf概述 在Netty中,ByteBuf是最基本、最核心的数据结构之一。实际上,Netty在设计时,就将ByteBuf作为数据处理的核心,因为I/O操作的数据流必定是…

    编程 2025-01-11
  • Netty面试题及答案详解

    一、Netty面试题及答案 在Netty的面试过程中,会涉及到不少面试题,下面列举并解答几个比较常见的问题。 1、Netty是什么? Netty是一个基于Java的NIO网络编程框…

    编程 2024-12-23
  • 使用Android Netty轻松实现网络通信

    一、什么是Android Netty Android Netty是一个开源的,基于Java NIO的客户端/服务器框架。Netty框架的出现使得开发者可以轻松地构建可维护和高性能协…

    编程 2024-12-22
  • Netty面试

    一、Netty面试题 Netty是一个高性能的网络通信框架,它的出现使得网络编程变得更加简单和高效。以下是一些常见的Netty面试题: 1. 请简要介绍Netty框架及其优点。 N…

    编程 2024-12-13
  • 如何使用Netty实现客户端断线重连

    一、Netty客户端离线监听 在Netty客户端中,由于网络原因,客户端会与服务端断开连接,但是我们希望客户端能够重新连接服务端,这就需要在客户端中监听客户端是否处于离线状态。 我…

    编程 2024-12-12

发表回复

登录后才能评论