netty 处理粘包的两种方案

博客介绍了Netty拆包粘包的两种解决方案。一是根据固定字符标志消息结束,用DelimiterBasedFrameDecoder实现,示例中用 ## 标志;二是根据固定长度标志消息结束,用FixedLengthFrameDecoder实现,示例中消息固定长度为14,还给出了完整代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一种方案  根据固定的字符标志一条消息的结束(DelimiterBasedFrameDecoder)

实现代码(这里用 ## 来标志一条消息的结束):

 ByteBuf buf = Unpooled.copiedBuffer("##".getBytes());
 sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf));

第二种方案  根据固定长度标志一条消息的结束(FixedLengthFrameDecoder)

实现代码(一条消息的固定长度为14):

 //2:根据固定长度标志一条消息的结束
 sc.pipeline().addLast(new FixedLengthFrameDecoder(14));

完整代码如下:

package com.netty.v0;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.ScheduledFuture;

import java.awt.*;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * \* Description:
 * \* Created with IntelliJ IDEA.
 * \* User: fdes
 * \* Date: 2018/8/24
 * \* Time: 11:47
 * \
 */
public class Server {
    public static void main(String[] args) throws InterruptedException {

        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup work = new NioEventLoopGroup();

        ServerBootstrap sb = new ServerBootstrap();
        sb.group(boss,work)
                .channel(NioServerSocketChannel.class)
                .childOption(ChannelOption.SO_KEEPALIVE,true)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel sc) throws Exception {
                        //1:根据固定的字符标志一条消息的结束
                        //ByteBuf buf = Unpooled.copiedBuffer("##".getBytes());
                        //sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf));


                        //2:根据固定长度标志一条消息的结束
                        //sc.pipeline().addLast(new FixedLengthFrameDecoder(14));

                        //3:也可以直接发送字符串,客户端需要添加字符串编码器,服务器端需要添加解码器
                        sc.pipeline().addLast(new StringDecoder());
                        sc.pipeline().addLast(new ServerHandler());
                    }
                });

        ChannelFuture cf = sb.bind(8888).sync();

        cf.channel().closeFuture().sync();
        work.shutdownGracefully();
        boss.shutdownGracefully();
    }
}
package com.netty.v0;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * \* Description:
 * \* Created with IntelliJ IDEA.
 * \* User: fdes
 * \* Date: 2018/8/24
 * \* Time: 17:02
 * \
 */
public class ServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("=================channelRegistered=============================" + ctx.channel().id());
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("=================channelActive=============================" + ctx.channel().id());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("=================channelRead=============================" + ctx.channel().id());

       ByteBuf bb = (ByteBuf) msg;
        byte[] bytes = new byte[bb.readableBytes()];
        bb.readBytes(bytes);
        System.out.println("收到客户端数据:" + new String(bytes));
        ctx.writeAndFlush(Unpooled.copiedBuffer("你好,已经收到你的消息。我是服务器".getBytes()));

      /* 测试直接收字符串消息代码
      String str = (String)msg;
       System.out.println(str);*/
    }


}
package com.netty.v0;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

/**
 * \* Description:
 * \* Created with IntelliJ IDEA.
 * \* User: fdes
 * \* Date: 2018/8/24
 * \* Time: 17:02
 * \
 */
public class Client {
    public static void main(String[] args) throws InterruptedException {

        EventLoopGroup work = new NioEventLoopGroup();

        Bootstrap sb = new Bootstrap();
        sb.group(work)
        .channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(new StringEncoder());
                ch.pipeline().addLast(new ClientHandler());
            }
        });

        ChannelFuture cf = sb.connect("127.0.0.1",8888).sync();

        cf.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty1##".getBytes()));
        cf.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty2##".getBytes()));
        cf.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty3##".getBytes()));
        cf.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty4##".getBytes()));
        cf.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty5##".getBytes()));
        cf.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty6##".getBytes()));


        //测试直接发送字符串消息
        //cf.channel().writeAndFlush("你好我来了,我是字符串!!!");

        cf.channel().closeFuture().sync();
        work.shutdownGracefully();
    }
}
package com.netty.v0;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * \* Description:
 * \* Created with IntelliJ IDEA.
 * \* User: fdes
 * \* Date: 2018/8/24
 * \* Time: 17:24
 * \
 */
public class ClientHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("=================channelRead=============================" + ctx.channel().id());
        ByteBuf bb = (ByteBuf) msg;
        byte[] bytes = new byte[bb.readableBytes()];
        bb.readBytes(bytes);
        System.out.println("收到服务器数据:" + new String(bytes));
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值