Netty拆包粘包

本文介绍了在Netty中如何处理拆包和粘包问题。通过使用定长消息、添加特殊分隔符或发送消息长度作为前缀来解决。在示例中,展示了客户端和服务器如何定义消息协议,并使用编码器和解码器来确保正确传输。服务器端通过ByteToMessageDecoder类解析接收到的数据,确保每条消息都被正确地拆分和处理。
摘要由CSDN通过智能技术生成

拆包

拆包是指netty传输数据时候,会把一条信息,拆成几部分。比如:"hello "拆成"he" 和 "llo"等,

粘包

粘包是指将多条信息连在一起 比如发送“hello”和"123",而受到的是 "hello123" 


解决方案:

  1. 消息定长,比如固定传100字符,不够的用空格补充
  2. 在尾部添加特殊字符
  3. 发送信息是发送信息长度

下面我们来看一下定长怎么用

客户端

@Data
public class MyMessageProtocol {

    //定义一次发送包体长度
    private int len;
    //一次发送包体内容
    private byte[] content;
}

public class NettyClientHandler extends SimpleChannelInboundHandler<MyMessageProtocol> {
    /**
     * 当客户端连接服务器完成就会触发该方法
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        for(int i = 0; i< 10; i++) {
            String msg = "检测拆包";
            //创建协议包对象
            MyMessageProtocol messageProtocol = new MyMessageProtocol();
            messageProtocol.setLen(msg.getBytes(CharsetUtil.UTF_8).length);
            messageProtocol.setContent(msg.getBytes(CharsetUtil.UTF_8));
            ctx.writeAndFlush(messageProtocol);
        }
    }
}

public class PackMessageEncoder extends MessageToByteEncoder<MyMessageProtocol> {
    @Override
    protected void encode(ChannelHandlerContext ctx, MyMessageProtocol msg, ByteBuf out) throws Exception {
        System.out.println("MyMessageEncoder encode 方法被调用");
        out.writeInt(msg.getLen());
        out.writeInt(msg.getLen());
        out.writeBytes(msg.getContent());
    }
}

服务端

public class PackNettyServerHandler extends SimpleChannelInboundHandler<MyMessageProtocol> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, MyMessageProtocol msg) throws Exception {
        System.out.println("====服务端接收到消息如下====");
        System.out.println("长度=" + msg.getLen());
        System.out.println("内容=" + new String(msg.getContent(), CharsetUtil.UTF_8));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

public class PackMessageDecoder extends ByteToMessageDecoder {

    int length = 0;

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        //int类型长度4
        if(in.readableBytes() >= 4) {
            //获取到长度
            if (length == 0){
                length = in.readInt();
            }
            if (in.readableBytes() < length) {
                System.out.println("当前可读数据不够,继续等待。。");
                return;
            }
            byte[] content = new byte[length];
            if (in.readableBytes() >= length){
                in.readBytes(content);

                //封装成MyMessageProtocol对象,传递到下一个handler业务处理
                MyMessageProtocol messageProtocol = new MyMessageProtocol();
                messageProtocol.setLen(length);
                messageProtocol.setContent(content);
                //交给下个handler处理
                out.add(messageProtocol);
            }
            length = 0;
        }
    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值