akkadotnet / akka.net

Canonical actor model implementation for .NET with local + distributed actors in C# and F#.
http://getakka.net
Other
4.7k stars 1.04k forks source link

Akka.IO & WSAEWOULDBLOCK socket error #3188

Closed andreichuk closed 6 years ago

andreichuk commented 6 years ago

Akka.NET version 1.3.2 Windows 10

Akka.IO does not handle non-fatal socket errors like WSAEWOULDBLOCK (System.Net.Sockets.SocketError.WouldBlock) which lead to closing of a connection. From MSDN: Resource temporarily unavailable. This error is returned from operations on nonblocking sockets that cannot be completed immediately, for example recv when no data is queued to be read from the socket. It is a nonfatal error, and the operation should be retried later.

When I'm trying to send a large (1 Mb or more) amount of data over the wire, I split it in chunks ~64kb and send one by one:

  1. Get a chunk of data (if anything left)
  2. Send it to Akka.IO
  3. Receive an acknowledgement
  4. Go to 1. With default Akka.IO tcp settings sending a file from a client to a server (both localhost) usually fails after few cycles because a socket throws WSAEWOULDBLOCK socket exception. It looks like the acknowledgement is sent by Akka.IO when data has been added to the socket's send buffer, not when it's actually has been sent. So overflowing the send buffer leads to the error. Decreasing chunk size to ~10 Kb helps but there is no guarantee that: a) there is only one "chunk sender" on the client at the moment; b) the server is able read/process even those 10 Kb fast enough.

I checked this code. It does not catch any exceptions, just checks a number of bytes written. Maybe there should be a catcher for WSAEWOULDBLOCK that waits for N milliseconds and then call the method again? Or you have better ideas? Help is appreciated! :)

Horusiath commented 6 years ago

Some notes from talk about this feature in DotNetty (also see code examples: 1 and 2):

Basically it attempts sync ops and switches to async when it would block otherwise. Now that there's true support for sync completions in .net core it might make sense to forego sync path completely for writes.

Horusiath commented 6 years ago

@andreichuk would you be able to give some reproducible example that could serve as a test scenario?

andreichuk commented 6 years ago

@Horusiath here you are https://github.com/andreichuk/AkkaIOTest

andreichuk commented 6 years ago

@Horusiath please check a fix prototype https://github.com/andreichuk/akka.net/commit/cbdec92b13c4c5dbfe13ce03dc8225d180ca71f9

Aaronontheweb commented 6 years ago

Resolved via https://github.com/akkadotnet/akka.net/pull/3206