我们首先看一下什么是拆包粘包:
解决方案:
这里面前两种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<SocketChannel>() {
@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()));