Azure / DotNetty

DotNetty project – a port of netty, event-driven asynchronous network application framework
Other
4.09k stars 977 forks source link

TcpSocketChannel Ubuntu 14.04 data corruption #286

Closed IvanAntipov closed 6 years ago

IvanAntipov commented 7 years ago

I have an issue with Ubuntu 14.04

Data is corrupted (extra lines inserted in the middle of the transmited file) during sending response from server. On Windows (local) the issue does not exists. On Unix data is corrupted. Without DotNetty, plain TCP Socket, everything works fine. With tcpdump i see that data is corrupted on Unix (server) side.

Repro (TestTCP application) in attachment Repro steps:

  1. Depoloy TestTCP on Ubuntu14.04 1.1 Build 1.2 Copy files 1.3 Enable connections to port 8183 ( ufw allow 8183) 1.4 Start listener ( dotnet TestTCP.dll netty)
  2. On Windows (client) side 2.1 dotnet TestTCP get __your_ubuntu_ip_address

Received bytes count should be equal to the size of index2.html file.

TestTCP.zip

caozhiyuan commented 7 years ago

@IvanAntipov Because Linux Socket Send has bug , it need .net core fix it. netty use noblocking and nodelay true socket

https://github.com/dotnet/corefx/issues/23672 https://github.com/dotnet/corefx/issues/23416

IvanAntipov commented 7 years ago

In my Repro there is an additional test. Listener which works without DotNetty. Without DotNetty data transmited correctly, no corruption. To run additional test without DotNetty run in point 1.4 of repro example dotnet TestTCP.dll listen instead of dotnet TestTCP.dll netty

caozhiyuan commented 7 years ago

@IvanAntipov try this
Socket.Blocking = false; then benchmark socket send in linux

IvanAntipov commented 7 years ago

@caozhiyuan I tested with Socket.Blocking = false Socket.NoDelay = true

No problem nor in windows nor in Unix. .Net works fine

As I can see from your example https://github.com/dotnet/corefx/issues/23672 You made double send: First Send and if result is SocketError.WouldBlock you execute second send SendAsync. Both time some data transmited. During the first send only small part of data is transmited. SendAsync transmit full data. The same problem i have when i use DotNetty, small part of data is transmited and then full data.

You dont need to make first Send, just SendAsync

To run NoBlock server examle type dotnet TestTCP.dll noblock

TestTCPNoBlock.zip

caozhiyuan commented 7 years ago

@IvanAntipov

https://github.com/Azure/DotNetty/blob/dev/src/DotNetty.Transport/Channels/Sockets/TcpSocketChannel.cs

if method DoWrite sharedBufferList not done use SendAsync

IvanAntipov commented 7 years ago

@caozhiyuan you said

now in linux ,I set socket blocking to true , dotnetty works ok.

How did you do it? Is it a temporary work around?

caozhiyuan commented 7 years ago

@IvanAntipov

   static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);

    protected AbstractSocketChannel(IChannel parent, Socket socket)
        : base(parent)
    {
        this.Socket = socket;
        this.state = StateFlags.Open;

        if (IsLinux)
            return;

        try
        {
            this.Socket.Blocking = false;
        }
        catch (SocketException ex)
        {
            try
            {
                socket.Dispose();
            }
            catch (SocketException ex2)
            {
                if (Logger.WarnEnabled)
                {
                    Logger.Warn("Failed to close a partially initialized socket.", ex2);
                }
            }

            throw new ChannelException("Failed to enter non-blocking mode.", ex);
        }
    }
nayato commented 7 years ago

would be interesting to see if it's another manifestation of this issue: https://github.com/Azure/DotNetty/issues/279 -- fix for this is in, so if you could build it from source or wait till 0.4.7 is out and try to see if it fixes things for you as well

caozhiyuan commented 7 years ago

@IvanAntipov i use sendasync on linux , sendasync core 2.0 no bug . take a look https://github.com/caozhiyuan/DotNetty/blob/dev/src/DotNetty.Transport/Channels/Sockets/TcpSocketChannel.cs#L333

caozhiyuan commented 7 years ago

@IvanAntipov and on linux set ChannelOutboundBuffer GetSharedBufferList max list count 1024 (https://github.com/dotnet/corefx/issues/23416#issuecomment-326745383) https://github.com/caozhiyuan/DotNetty/blob/dev/src/DotNetty.Transport/Channels/ChannelOutboundBuffer.cs#L365

IvanAntipov commented 7 years ago

@caozhiyuan Thank you, and sorry for the delay. I build your commit and merged it with StormHub/Http branch. All works on UNIX perfectly. Performance is excellent.

caozhiyuan commented 6 years ago

@IvanAntipov https://github.com/Azure/DotNetty/pull/299 fix it . the code before has a bit bug