Netty拆包粘包處理

一、Netty粘包解決方案

當我們使用Netty進行數據傳輸時,可能會遇到粘包現象,這種現象在單個包大小很小時很常見。但還是有方法來解決這個問題。下面介紹兩種最常見的解決方案。

1、FixedLengthFrameDecoder

該解碼器固定讀取指定消息長度的數據,如果每條消息都是固定長度的,則適合使用此解碼器。

2、DelimiterBasedFrameDecoder

該解碼器依賴於分隔符對接收到的數據進行拆分。常用的分隔符有”\r\n”、“\n”、“$”等。當每條消息中都包含有分隔符時,適合使用此解碼器。

二、Netty自定義粘包拆包

有些情況下,我們的數據並不能依靠固定長度或分隔符區分消息邊界,這時候就需要自定義粘包解包。下面給出代碼示例。

public class MyDecoder extends MessageToMessageDecoder<ByteBuf> {
   @Override
   protected void decode(ChannelHandlerContext ctx, ByteBuf in,
                         List<Object> out) throws Exception {
       while (in.readableBytes() >= 4) { //判斷是否有一個完整的消息
           int length = in.readInt(); //讀取消息長度
           if (in.readableBytes() < length) {//不足一個整包,重置讀指針
               in.readerIndex(in.readerIndex() - 4);
               return;
           }
           out.add(in.readBytes(length)); //讀取完整的數據包
       }
    }
}

以上示例中,我們繼承MessageToMessageDecoder類,並重寫decode方法,實現自定義解碼。在這個例子中,我們讀取了前4個字節作為數據包長度,然後根據長度讀取完整的數據包。

三、Netty分包粘包處理

1、使用LengthFieldBasedFrameDecoder

該解碼器先從ByteBuf中讀取指定長度的整型值,該整型值表示實際數據的長度。基於長度解碼器,可以解決TCP協議中粘包和分包問題。下面給出代碼示例。

public class MyDecoder extends LengthFieldBasedFrameDecoder {

    public MyDecoder() {
        super(ByteOrder.LITTLE_ENDIAN, 1024, 0, 4, 0, 4, true);
//        參數說明:LITTLE_ENDIAN: should length field byte order be littleEndian
//                  1024: maxFrameLength :表示數據幀最大長度
//                  0: lengthFieldOffset :表示數據長度字段值的起始位置,因為我們在發送數據時在數據包的最前面添加了一個4字節的int數據,所以這裡為0
//                  4:lengthFieldLength :表示長度字段所佔的字節數
//                  0:lengthAdjustment:一個長度調整值,讓解碼器從第一個字節開始;這裡為0
//                  4:initialBytesToStrip:去掉請求頭的幾個字段長度;這裡為4,因為前面我們在請求頭加上了4個字節的int數據表示真實數據的長度信息
//                  true:failFast :如果該參數設置為 true,則表示如果幀長度超過長度限制,就會立即拋出一個 TooLongFrameException,而不是等待後續字節到達,這樣可以防止太多的資源浪費在非預期包上
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        ByteBuf frame = (ByteBuf) super.decode(ctx, in);
        if (frame == null) {
            return null;
        }
        int realLength = frame.readInt();
        ByteBuf data = frame.slice(frame.readerIndex(), realLength);
        frame.release();
        return data;
    }
}

2、使用MessageToMessageCodec

該編碼器先編碼,再解碼,使用起來相對比較複雜。下面給出代碼示例。

public class MyMessageCodec extends MessageToMessageCodec<ByteBuf, Object> {

    @Override
    protected void encode(ChannelHandlerContext ctx, Object msg, List<Object> out) throws Exception {

        ByteBuf byteBuf = ctx.alloc().buffer();
        byteBuf.writeInt(0);  // 佔位長度
        byteBuf.writeBytes(msg.toString().getBytes(CharsetUtil.UTF_8));
        byteBuf.setInt(0, byteBuf.readableBytes() - 4); // 記錄實際長度
        out.add(byteBuf);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        int length = in.readInt();
        byte[] bytes = new byte[length];
        in.readBytes(bytes);
        out.add(new String(bytes, CharsetUtil.UTF_8));
    }
}

以上代碼實現了自定義編解碼器。在encode方法中,我們在寫入真實數據之前先寫入了4個字節的int類型數據,用於記錄真實數據的長度信息。在decode方法中,先讀取4個字節的int信息,再按照該長度讀取真實的數據。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/154762.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-11-16 14:15
下一篇 2024-11-16 14:15

相關推薦

  • gateway io.netty.buffer.poolchunk

    在本文中,我們將深入探討Netty中的一個基礎組件——PoolChunk,它是Netty中ByteBuf的一個關鍵實現,負責對ByteBuf進行緩存和管理。我們將從多個方面對該組件…

    編程 2025-04-28
  • 同時啟動兩個netty服務的實現方法

    本文將介紹如何同時啟動兩個netty服務的具體實現方法。 一、實現思路 為了同時啟動兩個netty服務,我們需要創建兩個不同的Channel,每個Channel都綁定到不同的服務端…

    編程 2025-04-27
  • netty和tomcat的比較

    一、簡介 Netty和Tomcat都是Java Web服務器,但它們的設計思想和應用場景不同。 Netty是一個高性能、異步事件驅動的網絡通信框架,可以用於實現WebSocket服…

    編程 2025-04-20
  • 深入理解Netty粘包

    一、什麼是粘包 網絡通信中消息的傳輸有兩個重要的問題,一個是粘包,一個是拆包。 粘包的概念就是發送方發送的多個小數據包被接收方一次性收到,這就像是把多個包“粘”在了一起。 造成粘包…

    編程 2025-04-12
  • Netty in Action:Java網絡編程的終極選擇

    一、基礎概念 Netty是由JBOSS的工程師Norman Maurer和Trustin Lee共同開發的,是一個高性能、異步、事件驅動的網絡編程框架。 相比於傳統的BIO(Blo…

    編程 2025-01-24
  • 深入探討Netty ByteBuf

    一、ByteBuf概述 在Netty中,ByteBuf是最基本、最核心的數據結構之一。實際上,Netty在設計時,就將ByteBuf作為數據處理的核心,因為I/O操作的數據流必定是…

    編程 2025-01-11
  • Netty面試題及答案詳解

    一、Netty面試題及答案 在Netty的面試過程中,會涉及到不少面試題,下面列舉並解答幾個比較常見的問題。 1、Netty是什麼? Netty是一個基於Java的NIO網絡編程框…

    編程 2024-12-23
  • 使用Android Netty輕鬆實現網絡通信

    一、什麼是Android Netty Android Netty是一個開源的,基於Java NIO的客戶端/服務器框架。Netty框架的出現使得開發者可以輕鬆地構建可維護和高性能協…

    編程 2024-12-22
  • Netty面試

    一、Netty面試題 Netty是一個高性能的網絡通信框架,它的出現使得網絡編程變得更加簡單和高效。以下是一些常見的Netty面試題: 1. 請簡要介紹Netty框架及其優點。 N…

    編程 2024-12-13
  • 如何使用Netty實現客戶端斷線重連

    一、Netty客戶端離線監聽 在Netty客戶端中,由於網絡原因,客戶端會與服務端斷開連接,但是我們希望客戶端能夠重新連接服務端,這就需要在客戶端中監聽客戶端是否處於離線狀態。 我…

    編程 2024-12-12

發表回復

登錄後才能評論