netty之tcp拆包粘包问题

# 解决tcp拆包,粘包问题
* 方案一:消息定长
* 方案二:在包尾部加上特殊字符进行分割
* 方案三:将消息分为消息头,消息体,类似与自定义协议

此处示例在尾部添加特殊字符解决拆包粘包问题

在 ServerBootstrap的childHandler方法里面(initChannel)添加 

// 设置特殊分隔符
ByteBuf buf = Unpooled.copiedBuffer("$end$".getBytes());
sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf));

// 设置字符串形式的解码
sc.pipeline().addLast(new StringDecoder());

算了,直接看代码吧:

Client.java

package zzq.neety02;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;

public class Client {
    public static void main(String[] args) throws InterruptedException {

        // 创建线程组
        NioEventLoopGroup group = new NioEventLoopGroup();

        // 创建辅助工具类
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group) //绑定线程组
                .channel(NioSocketChannel.class) // 指定 NIO 模式
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel sc) throws Exception {
                        // 设置特殊分隔符
                        ByteBuf buf = Unpooled.copiedBuffer("$end$".getBytes());
                        sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf));

                        // 设置字符串形式的解码
                        sc.pipeline().addLast(new StringDecoder());
                        sc.pipeline().addLast(new ClientHandler()); // 在这里配置数据接收处理的方法(类)
                    }
                });

        // 绑定连接地址
        ChannelFuture channelFuture = bootstrap.connect("127.0.0.1",8888).sync();

        // 向服务端发送消息
        channelFuture.channel().writeAndFlush(Unpooled.copiedBuffer("你好,一加一对于多少$end$".getBytes()));
        channelFuture.channel().writeAndFlush(Unpooled.copiedBuffer("你好,1234$end$".getBytes()));
        channelFuture.channel().writeAndFlush(Unpooled.copiedBuffer("你好,5678$end$".getBytes()));

        channelFuture.channel().closeFuture().sync();
        group.shutdownGracefully();
    }
}
 

ClientHandler.java

package zzq.neety02;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

public class ClientHandler extends ChannelHandlerAdapter {
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println( cause.toString() );
        System.out.println("出错了...");
        ctx.close();
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println( "注册成功..." );
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println( "激活成功..." );
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        String resp = (String) msg;

        System.out.println(  "收到了消息:" + msg );
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("我读完了...");
    }
}

 

Server.java

package zzq.neety02;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
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.string.StringDecoder;

import java.nio.Buffer;

public class Server {
    public static void main(String[] args) throws InterruptedException {
        //1 创建线两个程组
        //一个是用于处理服务器端接收客户端连接的
        //一个是进行网络通信的(网络读写的)
        NioEventLoopGroup pGroup = new NioEventLoopGroup();
        NioEventLoopGroup cGroup = new NioEventLoopGroup();

        //2.创建辅助工具类,用于服务器通信的一系列配置
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(pGroup,cGroup) // 绑定两个线程组
        .channel(NioServerSocketChannel.class) // 指定NIO模式
        .option(ChannelOption.SO_KEEPALIVE , true) // 设置保持连接
        .childHandler(new ChannelInitializer<SocketChannel>() {

            @Override
            protected void initChannel(SocketChannel sc) throws Exception {
                // 设置特殊分隔符
                ByteBuf buf = Unpooled.copiedBuffer("$end$".getBytes());
                sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf));

                // 设置字符串形式的解码
                sc.pipeline().addLast(new StringDecoder());

                // 3. 在这里配置具体的数据处理方法
                sc.pipeline().addLast(new ServerHandler());
            }
        });

        //4 进行绑定
        ChannelFuture cf1 = bootstrap.bind(8888).sync();
        //ChannelFuture cf2 = b.bind(8764).sync();
        //5 等待关闭
        cf1.channel().closeFuture().sync();
        //cf2.channel().closeFuture().sync();
        pGroup.shutdownGracefully();
        cGroup.shutdownGracefully();
    }
}

ServerHandler.java

package zzq.neety02;

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

import java.util.Base64;
import java.util.Date;

public class ServerHandler extends ChannelHandlerAdapter {

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 出现异常
        System.out.println( cause.toString() );
        ctx.close();
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("netty is register...");
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("netty is active...");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        String request = (String)msg;
        System.out.println("客户端发来消息:"+ request );
        String resp = "服务端响应:收到了你的消息==>" + new Date() + "$end$";

        ctx.writeAndFlush( Unpooled.copiedBuffer(resp.getBytes()) );
        System.out.println("返回数据:" + resp );
     }


}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值