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服务器接收到消息的时候,好像是把消息分成了两个包,第一个包是1024字节,第二个包是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时和接收时轻松完成。这可确保您的消息解码器仅看到表示完整消息的字节缓冲区。

请注意,您的帧处理程序应该放在您的首位,ChannelPipeline除非您还使用 SSL 处理程序和/或压缩处理程序,在这种情况下,应首先使用 SSL,然后是压缩,然后是帧处理程序。在管道中排在第一位意味着处理程序将首先处理入站事件,最后处理出站事件。

于 2013-08-24T15:50:03.410 回答