java - 通过Netty发送TCP数据包,Netty是将数据分成不同的数据包?

标签 java sockets networking tcp netty

我目前正在使用 Netty 4.0.7.Final 编写一个通过 TCP 接收图像(大小:~10k)的服务器。 我修改了 Netty 的示例 echo 客户端处理程序,将文件读取为字节,然后将其发送到我的 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 为什么要这样做?有没有办法一次性获取完整的数据包?

非常感谢。

最佳答案

如果您想从处理程序中提取碎片,您需要构建消息。这可以通过使用 LengthFieldPrepender 轻松完成。发送时和 LengthFieldBasedFrameDecoder接收时。这可确保您的消息解码器仅看到代表完整消息的字节缓冲区。

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

关于java - 通过Netty发送TCP数据包,Netty是将数据分成不同的数据包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18420049/

相关文章:

networking - 更改 docker 容器 IP 地址

java - 排序方法运行时崩溃

networking - 从Virtualbox Guest到DynDNS地址的SSH

java - 从批处理文件中独立执行 Jar

sockets - SOCKET_RWGROUP=ClamAv 中的后缀?

通过套接字的 iOS 连接不起作用

android - 不能同时运行两个或多个安卓模拟器

c++ - ASIO 客户端服务器在同一台 PC 上连接正常,但在本地网络上失败

java - 无法通过蓝牙写入十六进制字节

java - MessageDigest ArrayIndexOutOfBoundsException