netty如何解決粘包和半包


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

解決方案

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

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

消息定長格式解決

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

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獲取固定長度字符來解決粘包半包問題

 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來消息頭和消息體來解決粘包和半包問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章