我们首先看一下什么是拆包粘包:

解决方案:

这里面前两种netty是帮我们实现了的

我们在netty中如何解决呢?我们通过设置特殊分隔符,然后传递数据的时候,把特殊分隔符放到最后即可:
来看server端代码:
- public class ServerDecoder {
- public static void main(String[] args) throws Exception {
- //1 第一个线程组,是用于接收 client 端连接的
- EventLoopGroup bossGroup = new NioEventLoopGroup();
-
- //2 第二个线程组,是用于实际的业务处理操作的
- EventLoopGroup workerGroup = new NioEventLoopGroup();
-
- //3 创建一个辅助类 ServerBootstrap, 就是对我们的 server 端进行一系列配置
- ServerBootstrap b = new ServerBootstrap();
- // 把两个工作线程组加进来
- b.group(bossGroup, workerGroup)
- // 我要指定使用 NioServerSocketChannel 这种类型的通道
- .channel(NioServerSocketChannel.class)
- // 一定要使用 childHandler 去绑定具体的事件处理器
- .childHandler(new ChannelInitializer
() { -
- @Override
- protected void initChannel(SocketChannel sc) throws Exception {
- // 设置特殊分隔符
- ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());
- sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, buf));
- // 设置字符串形式的解码
- sc.pipeline().addLast(new StringDecoder());
- sc.pipeline().addLast(new ServerHandlerDecoder());
- }
- })
- .option(ChannelOption.SO_BACKLOG, 128)
- // 保持连接
- .option(ChannelOption.SO_KEEPALIVE, true);
-
- // 使用指定的端口进行监听
- ChannelFuture f = b.bind(8765).sync();
- f.channel().closeFuture().sync();
- bossGroup.shutdownGracefully();
- workerGroup.shutdownGracefully();
- }
- }
注意看意思代码的 initChannel 方法
initChannel方法改成这样:
@Override
protected void initChannel(SocketChannel sc) throws Exception {
// 设置特殊分隔符,
ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());
sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, buf));
// 设置字符串形式的解码
sc.pipeline().addLast(new StringDecoder());
sc.pipeline().addLast(new ServerHandler());
}
以上代码注意要区分先后顺序,一定要先是 DelimiterBasedFrameDecoder, 再到, StringDecoder,
最后才是我们自己的业务处理逻辑 ServerHandler
client端的initChannel方法改如下:
protected void initChannel(SocketChannel socketChannel) throws Exception {
ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());
socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, buf));
// 设置字符串形式的解码
socketChannel.pipeline().addLast(new StringDecoder());
socketChannel.pipeline().addLast(new ClientHandler());
}
连接时的代码如下:
ChannelFuture cf1 = b.connect("127.0.0.1", 8765).sync();
cf1.channel().writeAndFlush(Unpooled.copiedBuffer("bbbbb$_".getBytes()));
cf1.channel().writeAndFlush(Unpooled.copiedBuffer("ccc$_".getBytes()));