2

現在、Netty 4.0.7.Final を使用して、TCP 経由で画像 (サイズ: ~10k) を受信するサーバーを作成しています。Netty のサンプル エコー クライアント ハンドラーを変更して、ファイルをバイト単位で読み取り、それを Netty サーバーに送信するようにしました。

public EchoClientHandler(int firstMessageSize) throws IOException {
    File image = new File("google.jpeg");
    byte[] imageBytes = FileUtils.readFileToByteArray(image);
    byte[] bytes = Base64.encodeBase64(imageBytes);
    String base64 = new String(bytes);
    //System.out.println("base64="+ base64);
    firstMessage = Unpooled.copiedBuffer(base64, CharsetUtil.UTF_8);
}

私のテスト画像は 9k で、画像全体が Netty ログ経由で送信されていることがわかります

io.netty.handler.logging.LoggingHandler logMessage
INFO: [id: 0x132baef0, /127.0.0.1:49710 => localhost/127.0.0.1:2112] WRITE(11964B)

ただし、Netty サーバーがメッセージを受信すると、メッセージを 2 つのパケットに分割しているように見えます。最初のパケットは 1024 バイト、2 番目のパケットは 10940 バイトで、合計すると 1024 + 10940 = 11964 バイトになります (画像)

2013-08-24 22:56:33,700 [nioEventLoopGroup-3-1] INFO  MessageDecoder - capacity = 1024
2013-08-24 22:56:33,700 [nioEventLoopGroup-3-1] INFO  MessageDecoder - readable bytes = 1024
2013-08-24 22:56:33,709 [nioEventLoopGroup-3-1] INFO  MessageDecoder - capacity = 16384
2013-08-24 22:56:33,710 [nioEventLoopGroup-3-1] INFO  MessageDecoder - readable bytes = 10940

これが私のデコーダーの外観です(デコーダーがそれと関係があるとは思えませんが、デコーダーに到達する前にNettyがこれを処理しているようです)

public class MessageDecoder extends ByteToMessageDecoder {

private static final Logger LOGGER = LoggerFactory.getLogger(MessageDecoder.class);

@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
    // Convert to String first
    LOGGER.info("capacity = " + in.capacity());
    LOGGER.info("readable bytes = " + in.readableBytes());
    String rawString = in.readBytes(in.readableBytes()).toString(CharsetUtil.UTF_8);    
    LOGGER.info("Received base64 String={}", rawString);
}

また、多数のファイルを試してみましたが、Netty は常にメッセージを 1024 バイト + 残りのファイルの任意のサイズのパケットに分割しているようです??

なぜNettyがこれをしているのか疑問に思っています。完全なパケットを一度に取得する方法はありますか?

本当にありがとう。

4

1 に答える 1

3

ハンドラーから断片化を抽象化したい場合は、メッセージをフレーム化する必要があります。LengthFieldPrependerこれは送信時と受信時を利用することで簡単に行うことができますLengthFieldBasedFrameDecoder。これにより、メッセージ デコーダーは完全なメッセージを表すバイト バッファーのみを認識するようになります。

ChannelPipelineSSL ハンドラーや圧縮ハンドラーを使用している場合を除き、フレーム ハンドラーを最初に指定する必要があります。この場合は、SSL を最初に指定し、次に圧縮を指定し、その後にフレーム ハンドラーを指定する必要があります。パイプラインで最初になるということは、ハンドラーが最初にインバウンド イベントを処理し、最後にアウトバウンド イベントを処理することを意味します。

于 2013-08-24T15:50:03.410 に答える