Netty接着問題処理

3560 ワード

Netty接着問題処理
key words:netty粘着解包半包TCP
一般的なTCP接着/分解解決方法
  • 定長メッセージ、例えば各メッセージの長さが固定され、スペースが足りない
  • は、リターン改行符号で分割する、Ftpプロトコル
  • のようなパケットの末尾に分割符号を付ける.
  • メッセージ分割、ヘッダは長さ(メッセージの全長またはメッセージボディの長さ)であり、通常、ヘッダはint 32で
  • を表す.
  • 複雑なアプリケーション層プロトコル
  • Nettyのいくつかのソリューション
    特殊セパレータデコーダ:DelimiterBasedFrameDecoder
    クライアント送信メッセージ
    String message = "netty is a nio server framework &"
                    +"which enables quick and easy development &"
                    +"of net applications such as protocol &"
                    +"servers and clients!";

    サービス側追加デコーダ:DelimiterBasedFrameDecoder
    ByteBuf delimiter = Unpooled.copiedBuffer("&".getBytes());
    ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,delimiter));
    //1024           ,            ,               
    ch.pipeline().addLast(new StringDecoder());
    ....
    ch.pipeline().addLast(new StringEncoder());

    印刷出力:
        :[netty is a nio server framework ]
        :[which enables quick and easy development ]
        :[of net applications such as protocol]
        :[servers and clients!]

    パラメータの説明:
    public DelimiterBasedFrameDecoder(int maxFrameLength, ByteBuf delimiter) {
        this(maxFrameLength, true, delimiter);
    }
    maxFrameLength:         
    
    stripDelimiter:          
    
    failFast: true, frame    maxFrameLength    TooLongFrameException  , false,          
    
    delimiter:   

    固定長デコーダ:FixedLengthFrameDecoder
    パラメータの説明:
  • frameLength:フレームの固定長
  • サービス側
    ch.pipeline().addLast(new FixedLengthFrameDecoder(30));//             30
    
    
    public void channelRead(ChannelHandlerContext ctx, Object msg)
            throws Exception {
        System.out.println("     msg:["+msg+"]");
        ByteBuf echo=Unpooled.copiedBuffer(MESSAGE.getBytes());
        ctx.writeAndFlush(echo);
    }

    クライアント
    ch.pipeline().addLast(new FixedLengthFrameDecoder(30));//       

    エンベロープの固定されていない長さに基づくデコーダ:L e n g thFieldBasedFrameDecoder
    パラメータの説明
  • maxFrameLength:復号フレームの最大長
  • lengthFieldOffset:長さ属性の開始ビット(オフセットビット)で、パケットには大きなパケットの長さ全体のバイトが格納され、このバイトの実際の位置は
  • である.
  • lengthFieldLength:長い属性の長さ、すなわち大きなパケットの長さ全体を格納バイトが占める長さ
  • .
  • lengthAdjustmen:長さ調整値で、全長がパッケージ長を含むと定義された場合、情報長を修正します.
  • initialBytesToStrip:スキップされたバイト数、必要に応じてlengthFieldLengthバイトをスキップして、受信側が「長さ属性」を含まないコンテンツ
  • を直接受け入れるようにします.
  • failFast:true、frame長がmaxFrameLengthを超えると直ちにTooLongFrameException異常、false、全フレームを読み出して異常
  • を再報告する
    備考:長さ解析ミス(大きすぎると、このバッグを直接捨てる;小さすぎる、1、nettyは異常を投げ出さない;2、検査は通じない)
      :
    int frameLengthInt = (int) frameLength;
    if (in.readableBytes() < frameLengthInt) {
        return null;
    }

    梱包時にLengthFieldPrependerを併用すると、梱包長を付けやすくなります
    パケットヘッダ追加総パケット長バイト:LengthFieldPrepender
    パブリッシュ時に、フレームのヘッダに長さパラメータの説明を自動的に追加します.
  • lengthFieldLength:長さ属性のバイト長
  • lengthIncludesLengthFieldLength:false、長さバイトは全長に算入されず、true、全長に算入:pipeline.addLast("frameEncode", new LengthFieldPrepender(4, false));

  • 公式の説明:
       ,   
    +----------------+  
    | "HELLO, WORLD" |  
    +----------------+
    
                   ,    
    +--------+----------------+ 
    + 0x000C | "HELLO, WORLD" | 
    +--------+----------------+
    
      lengthIncludesLengthFieldLength   true,    (      )
    +--------+----------------+ 
    + 0x000E | "HELLO, WORLD" | 
    +--------+----------------+

    コメント
    その时、问题と记录を解决する时、公式サイトといくつかのブログを调べて、もし中の内容がcopyの地方があるならば、urlを伝言してください、私はあなたの文章の引用を上に置きます