I created this small example. I have an EchoServer
on Port 8080 and a LogServer
on Port 9090 (exemplary in this example). Both are started on the same machine (with Server
, which contains the main).
Server started on port 8080
Server started on port 9090
As soon a client -- via telnet
-- connects, the EchoServer
establishes a connection to the LogServer
. Now I am entering a long text, let's say 5000 character (see the long_text in the example), even if bash cannot handle it:
EchoServer Received: 1024
LogServer Received: 1024
EchoServer Received: 2048
LogServer Received: 2048
EchoServer Received: 1025
LogServer Received: 1025
If I enter the text again, I am getting:
EchoServer Received: 2048
LogServer Received: 2048
EchoServer Received: 2049
LogServer Received: 2049
Let's do it again:
EchoServer Received: 3072
EchoServer Received: 1025
LogServer Received: 3072
LogServer Received: 1025
And again:
EchoServer Received: 4096
EchoServer Received: 1
LogServer Received: 4096
LogServer Received: 1
The last time:
EchoServer Received: 4097
LogServer Received: 4097
My observation:
First of all, the data is fragmented. Additionally, each time the fragmends are extended by 1024 bytes (1024,2048,3072,4096,...). I guess the last behavious is because of the TCP slow start.
How can I achive the forwarding to the .LogServer
without fragmentation, such my text will arrive as one single message? I guess the problem is, how I connect to the LogServer
[EDIT1]
I changed the logs. It seems, that it's already happening between telnet
and the EchoSever
. Anyway, I still have the problem in the real environment. The whole message (some Kilobyte) is arriving via WebSockets and the Forwarding to another Connection is fragmented.
[EDIT2]
I did some more research (with wireshark -- the log). I guess it has noting to do with TCP Slow Start. The data (I was sending 4095 times the letter A
) arriving on the machine as three correct TCP packets:
- Frame 1 (1506 bytes) with 1440 bytes TCP data (
41 41 41 ... 41 41 41
/HEX) - Frame 2 (1506 bytes) with 1440 bytes TCP data (
41 41 41 ... 41 41 41
/HEX) - Frame 3 (1283 bytes) with 1217 bytes TCP data (
41 41 41 ... 41 0d 0a
/HEX)
All 4095 A
characters + CRLF arrived as expected.
The EchoServer
said:
EchoServer Received: 1024
EchoServer Received: 2048
EchoServer Received: 1025
It also received the 4095 characters + CRLF, but it is different fragmented than the TCP segments (exactly same as the first log above). How can I avoid this Netty behavior?
You require a FrameDecoder in your pipeline can which assemble bytes from the network into complete frames. In your case I think you need to combine the StringDecoder and DelimiterBasedFrameDecoder. Take a look at the Telnet example and specifically the TelnetServerPipelineFactory
In non-blocking I/O, there's no practical way to get the number of available bytes in socket receive buffer. Because of that problem, Netty predicts the number of available bytes. It starts from 1024 and then increases the prediction depending the number of read bytes. You can shcnage this behavior by employing a different prediction algorithm.
The default implementation is
AdaptiveReceiveBufferSizePredictor
and you might want to take a look into its source code to write your own one.However, no matter what prediction algorithm you choose, you have to keep in mind that TCP/IP is a streaming protocol, which means you can always get messages in a split or merged form. Please refer to the user guide: http://netty.io/docs/stable/guide/html/ (See the 'Dealing with a Stream-based Transport' section.)