netty如何解決粘包和半包


TCP是一個基於「流」的協議,所謂流就像河裏的水沒有嚴格的界限。TCP底層並不瞭解上層業務的具體實現,它會根據TCP緩衝區的具體狀況進行劃分,因此就可能會出現業務上一個完整的TCP包可能會拆分紅多個小包進行發送,也可能多個小包被組裝成一個大包進行發送,從而致使了TCP中的粘包和半包問題。socket

解決方案

  1. 消息定長,每發送一次消息,在接收消息的同時截取固定長度的字節。
  2. 以某種分隔符進行分割。
  3. 把消息封裝成消息頭和消息體。

netty中的粘包和半包解決方案

消息定長格式解決

經過添加DelimiterBasedFrameDecoder來解決粘包半包問題ide

b.group(bossGroup, workGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 1024)
                .handler(new LoggingHandler())
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes());
                        socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter));
                        //socketChannel.pipeline().addLast(new FixedLengthFrameDecoder(10));
                        socketChannel.pipeline().addLast(new StringDecoder());
                        socketChannel.pipeline().addLast(new EchoServerHandler());
                    }
                });

根據特定字符分割解決

經過添加FixedLengthFrameDecoder獲取固定長度字符來解決粘包半包問題netty

b.group(bossGroup, workGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 1024)
                .handler(new LoggingHandler())
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        //ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes());
                        //socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter));
                        socketChannel.pipeline().addLast(new FixedLengthFrameDecoder(10));
                        socketChannel.pipeline().addLast(new StringDecoder());
                        socketChannel.pipeline().addLast(new EchoServerHandler());
                    }
                });

根據消息頭和消息體封裝解決

經過ObjectDecoder和ObjectEncoder來消息頭和消息體來解決粘包和半包問題。code

相關文章
相關標籤/搜索