我创建了this small example。我在端口8080上有EchoServer
,在端口9090上有LogServer
(在此示例中为示例)。两者都在同一台机器上启动(Server
,其中包含主机)。
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 ]
我更改了日志。看起来,它已经发生在telnet
和EchoSever
之间。 无论如何,我仍然在真实环境中遇到问题。整个消息(一些Kilobyte)通过WebSockets到达,转发到另一个连接是分散的。
[ EDIT2
我做了更多研究(使用wireshark - the log)。我想它与TCP Slow Start有关。到达机器的数据(我发送了4095次字母A
)作为三个正确的TCP数据包:
41 41 41 ... 41 41 41
/ HEX)41 41 41 ... 41 41 41
/ HEX)41 41 41 ... 41 0d 0a
/ HEX)所有4095 A
个字符+ CRLF按预期到达。
EchoServer
说:
EchoServer Received: 1024
EchoServer Received: 2048
EchoServer Received: 1025
它还收到了4095个字符+ CRLF,但它与TCP段不同(与上面的第一个日志完全相同)。我怎样才能避免这种网络行为?
答案 0 :(得分:2)
在非阻塞I / O中,没有实用的方法来获取套接字接收缓冲区中的可用字节数。由于这个问题,Netty 预测可用字节数。它从1024开始,然后根据读取字节数增加预测。您可以通过采用不同的预测算法来解决此问题。
默认实现是AdaptiveReceiveBufferSizePredictor
,您可能需要查看其源代码以编写自己的源代码。
但是,无论您选择何种预测算法,都必须记住TCP / IP是一种流协议,这意味着您始终可以以拆分或合并的形式获取消息。请参阅用户指南:http://netty.io/docs/stable/guide/html/(请参阅“处理基于流的传输”部分。)
答案 1 :(得分:0)
您需要在管道中使用FrameDecoder,它可以将来自网络的字节组装成完整的帧。在你的情况下,我认为你需要结合StringDecoder和DelimiterBasedFrameDecoder。请查看Telnet example,特别是TelnetServerPipelineFactory