通信フレームワークnetty 5.0教程三:TCPの粘着パッケージ/取り外し問題


TCPプログラミングに精通している読者は、サービス端末であろうと、クライアントであろうと、メッセージを読んだり、送信したりするときは、TCPベースの粘パケット/解凍メカニズムを考慮する必要があることを知っているかもしれない。TCPの粘着パケットの問題を考慮しないと、データの読み込みエラーを引き起こす可能性があります。本論文では、どのようにしてNetty 5.0を使ってTCPの粘パケットを解決するかを説明します。
netty 5.0には非常に便利なトランスポート解像器があります。LengthField BasedFrame Decoder。以下はLengthFieldBasedFrame Decoderの構造方法です。

/**
* Creates a new instance.
*
* @param maxFrameLength
* the maximum length of the frame. If the length of the frame is
* greater than this value, {@link TooLongFrameException} will be
* thrown.
* @param lengthFieldOffset
* the offset of the length field
* @param lengthFieldLength
* the length of the length field
* @param lengthAdjustment
* the compensation value to add to the value of the length field
* @param initialBytesToStrip
* the number of first bytes to strip out from the decoded frame
*/
public LengthFieldBasedFrameDecoder(
int maxFrameLength,
int lengthFieldOffset, int lengthFieldLength,
int lengthAdjustment, int initialBytesToStrip) {
this(
maxFrameLength,
lengthFieldOffset, lengthFieldLength, lengthAdjustment,
initialBytesToStrip, true);
}
maxFrame Length:パケット最大許容長さ
lengthFieldOffset:長さフィールドのオフセット量
レングスフィールドの長さ
lengthAdjust ment:補正値
initial Bytes ToStrip:デコーダから除外された長さ(上の長さフィールドに設定された長さ)
このように見ると、nettyサービスの中に解析器を追加するだけで、TCPの粘包問題を解決できます。サービスコードは全部貼り付けません。変更された部分だけ貼ってください。分からない方は前二篇のキティちゃんの文章を見てください。

bootstrap.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel socketChannel)
throws Exception {
ChannelPipeline p = socketChannel.pipeline();

// , 4
p.addLast(new LengthFieldBasedFrameDecoder(1024 * 1024, 0,
4, 0, 4));

//
p.addLast(new IdleStateHandler(15, 30, 30, TimeUnit.SECONDS));
p.addLast(new NettyIdleStateHandler());

p.addLast(new NettyServerHandler());
}
});
解析器を追加すると、約束通りにサーバにパケットを送信する際に、パケットヘッダに値を追加して、後のデータのバイト長を説明するだけで良いです。
クライアントがパケットを送信する時のフォーマットは以下の通りです。

public static ByteBuf newProtocol(String message)
throws UnsupportedEncodingException {

byte[] req = message.getBytes(Constant.UTF8);
ByteBuf pingMessage = Unpooled.buffer();
pingMessage.writeInt(req.length);
pingMessage.writeBytes(req);

return pingMessage;
}
このようにTCPのクラッチ/クラッチの問題は簡単に楽しく解決できます。