【问题标题】:Netty - FramingNetty - 框架
【发布时间】:2012-02-29 20:31:05
【问题描述】:

我创建了this small example。我在端口 8080 上有一个 EchoServer,在端口 9090 上有一个 LogServer(本例中的示例)。两者都在同一台机器上启动(Server,其中包含 main)。

Server started on port 8080
Server started on port 9090

一旦客户端通过telnet 连接,EchoServer 就会建立到LogServer 的连接。现在我正在输入一个长文本,比如说 5000 个字符(参见示例中的 long_text),即使 bash 无法处理它:

EchoServer Received: 1024
LogServer Received: 1024
EchoServer Received: 2048
LogServer Received: 2048
EchoServer Received: 1025
LogServer Received: 1025

如果我再次输入文本,我会得到:

EchoServer Received: 2048
LogServer Received: 2048
EchoServer Received: 2049
LogServer Received: 2049

让我们再做一次:

EchoServer Received: 3072
EchoServer Received: 1025
LogServer Received: 3072
LogServer Received: 1025

再说一遍:

EchoServer Received: 4096
EchoServer Received: 1
LogServer Received: 4096
LogServer Received: 1

最后一次:

EchoServer Received: 4097
LogServer Received: 4097

我的观察:

首先,数据是碎片化的。此外,每次将片段扩展 1024 字节(1024,2048,3072,4096,...)。 我猜最后一个行为是因为 TCP 启动慢

我怎样才能在没有碎片的情况下转发到LogServer,这样我的文本将作为一条消息到达?我想问题是,how I connect to the LogServer

[EDIT1]

我更改了日志。看来,它已经在telnetEchoSever 之间发生了。 反正我在真实环境中还是有问题的。整个消息(一些千字节)通过 WebSockets 到达,转发到另一个连接是碎片化的。

[EDIT2]

我做了更多的研究(使用wireshark -- the log)。我想这与 TCP 慢启动有关。数据(我发送了字母A 的 4095 倍)作为三个正确的 TCP 数据包到达机器:

  1. 第 1 帧(1506 字节)和 1440 字节 TCP 数据 (41 41 41 ... 41 41 41/HEX)
  2. 带有 1440 字节 TCP 数据 (41 41 41 ... 41 41 41/HEX) 的第 2 帧(1506 字节)
  3. 带有 1217 字节 TCP 数据 (41 41 41 ... 41 0d 0a/HEX) 的第 3 帧(1283 字节)

所有 4095 个A 字符 + CRLF 按预期到达。

EchoServer 说:

EchoServer Received: 1024
EchoServer Received: 2048
EchoServer Received: 1025

它也收到了 4095 个字符 + CRLF,但它与 TCP 段的碎片不同(与上面的第一个日志完全相同)。如何避免这种 Netty 行为?

【问题讨论】:

    标签: tcp netty


    【解决方案1】:

    在非阻塞 I/O 中,没有实用的方法来获取套接字接收缓冲区中的可用字节数。由于这个问题,Netty 预测可用字节数。它从 1024 开始,然后根据读取的字节数增加预测。您可以通过使用不同的预测算法来消除这种行为。

    默认实现是AdaptiveReceiveBufferSizePredictor,您可能需要查看它的源代码来编写自己的。

    但是,无论您选择哪种预测算法,您都必须牢记 TCP/IP 是一种流式协议,这意味着您始终可以以拆分或合并的形式获取消息。请参阅用户指南:http://netty.io/docs/stable/guide/html/(请参阅“处理基于流的传输”部分。)

    【讨论】:

    • 感谢您提供一些详细信息。最后,我在应用程序端实现了类似LengthFieldPrepender 的东西。因此,我将 TCP 行为保持原样并在应用程序中处理它,
    • 将值设置为标准以太网帧大小 - 1500 字节是否有意义?在我看来,它应该改进 Netty,而不是扩展 ChannelBuffer - 保存一些说明 - 用于单个完整帧。
    • 顺便说一句:我说得对吗,TCP-Paket 的FIN 总是向管道发送消息?
    【解决方案2】:

    您的管道中需要一个 FrameDecoder 可以将来自网络的字节组装成完整的帧。在您的情况下,我认为您需要将 StringDecoder 和 DelimiterBasedFrameDecoder 结合起来。看看Telnet example,特别是TelnetServerPipelineFactory

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-15
      相关资源
      最近更新 更多