locked
socket.Receive() on blocking socket throwing WSAEWOULDBLOCK exception? RRS feed

  • Question

  • I'm using a UDP socket for network communication with socket.Blocking == true and SocketOption(ReceiveTimeout) set. After several thousand packet exchanges, socket.Receive() starts throwing WSAEWOULDBLOCK (SocketException.ErrorCode == 10034) and seemingly continues to do so indefinitely about every second or third call to socket.Receive().
     
    Can someone shed some light on what might cause socket.Receive() to throw a WSAEWOULDBLOCK exception on a socket with Blocking == true? I wouldn't expect a WSAEWOULDBLOCK exception on a blocking socket.

    This is happening with .Net 2.0 Beta2 on WindowsXP Pro with service pack 2 (and updates).

    Thanks,
    Ray

    Tuesday, November 1, 2005 3:48 PM

Answers

  • As a temporary workaround you may want to explicitly set the Blocking property to true right before you call receive.

    client.Blocking =
    true;
    client.Receive(buffer);

    Mariya
    Friday, November 11, 2005 2:04 AM
    Moderator
  • First, let me say you were right about the WSAEWOULDBLOCK exception. Thanks for bringing this to our attention. We will be working on getting this fixed.

    For 10060, what I meant was that you could ge  it due to the receive timing out on a blocking socket.(as was the case with your example code). You can see the socket error codes and descriptions here.
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp

    For 10054 (WSAECONNRESET) you may want to check the MSDN description of recvfrom and see when you get WSAECONNRESET
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/recvfrom_2.asp
    The ideia is that when  there is no UDP listener, the stack receives ICMP port unreachable error and delivers this to the app via WSAECONNRESET. A single send may not be enough to trigger this. The stack does not keep track of every unreachable packet, since you may be sending to different destinations. That’s just too much overhead. Try sending a few packets and then call recv, which should fail with WSAECONNRESET. The design is such that an app isn’t blindly sending packets into a black hole.

    Let me know if this post helped.
    Mariya Atanasova

    Friday, November 11, 2005 11:43 PM
    Moderator

All replies

  • Please try this on the RTM version.
    I believe we fixed some issues like this since beta2
    Lets know if you still encounter this error.
    Thanks for reporting this.
    Tuesday, November 1, 2005 4:48 PM
    Moderator
  • Given that it will be awhile before the channel gets stuffed and I can get my hands on a golden development environment to try this against  (I'm not a MSDN subscriber), might there be another work around?

    Thanks,
    Ray
    Wednesday, November 2, 2005 3:53 AM
  • Not Really!!!!
    We just released .NEt 2.0 SDK and Redist.
    http://msdn.microsoft.com/netframework/downloads/updates/default.aspx

    So you can uninstall the previous Beta2 / SDK and install the new one.
    VS may not work. So you can try this on a machine where you can
    just install the SDK and Redist.

    Wednesday, November 2, 2005 5:13 AM
    Moderator
  • I still receive this exception on a clean install of XP Pro service pack 2, +.Net 2.0 release SDK. Currently, my workaround is to just ignore the error and call socket.Receive() again for a maximum of 10 retries (it usually succeeds on the second or third attempt). I have yet to see the workaround fail but without knowing the cause of the problem, I can't say that it won't.

    - Ray
    Monday, November 7, 2005 11:18 PM
  • Thanks but I would like to see if there is a bug.
    Can you please send me your code to my email address
    Durgaprasad.Gorti@microsoft.Com.dontspam [remove the dontspam]
    If I can repro this bug here I will get that fixed.
    Also let us know if this is somehow stopping you from getting your app work.
    Once again, I need to repro this locally to be able to tell you exactly what is wrong.
    Thanks for your patience

    Monday, November 7, 2005 11:51 PM
    Moderator
  • In general, my code would not be helpful in trying to reproduce the problem since the other end of the connection is an embedded system. If there is any data I might be able to provide to help determine the problem I'd be happy to help.

    Within my code, I'm calling the socket on two different threads but synchronizing with a lock on the socket. The documentation for the Socket class states the following:

    To process communications using separate threads during execution, use the following methods, which are designed for asynchronous operation mode.

    This seems to indicate a one to one relation between multi-threaded applications and the asynchronous methods. I'm not sure why the two would be directly correlated but that's my interpretation. Am I reading this wrong? Can I sychronize calls to Send/Receive on multiple threads using one socket? Is there any Socket state associated with the calling thread?

    Converting to Async calls doesn't appear to be as easy as I had hoped which is what I was going to do in order test the theory that this might be the root of my problem. As far as I can tell with simple tests, the socket timeout setting is no longer honored in async methods so async thread management becomes a problem in itself.


    - Ray

    Wednesday, November 9, 2005 12:36 AM

  • I'm (somewhat) able to reproduce the bug with the following code. On my machine it takes about 2 seconds before the first exception is hit. After the first exception, it's pretty much a continuous problem. I am baffled by the first exception however since the error talks about server response when SocketType is Dgram and the ProtocolType is Udp (I never received this exception in my application). Following that exception, the socket returns the "would block" exception event though the socket is set to Blocking.

    Output follows listing:

    Code Block

    using System;
    using System.Net.Sockets;
    using System.IO;
    using System.Threading;
    using System.Net;

    namespace ConsoleApplication3
    {

    class Program
    {
        // setup read and write sockets
        static Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        static Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

        static void Server()
        {
            byte[] buffer = new byte[10];

            while (true)
            {
                try
                {
                    server.Receive(buffer);
                }

                catch (Exception e)
                {
                    Console.Out.WriteLine("Server exception: " + e.Message + " : Blocking = " + server.Blocking);
                }

                Console.Out.WriteLine("Server: received.");
                server.Send(buffer);
            }
        }

        static void Main(string[] args)
        {
            // sychronize output
            Console.SetOut(TextWriter.Synchronized(Console.Out));

            IPAddress addr = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];

            server.Connect(addr, 0);

            client.Connect(server.LocalEndPoint);

            server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 500);
            client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 500);

            Thread serverThread = new Thread(new ThreadStart(Server));

            byte[] buffer = new byte[6];

            // client loop

            while (true)
            {
                client.Send(buffer);

                try
                {
                    client.Receive(buffer);
                    Console.Out.WriteLine("Client received.");
                }

                catch (Exception e)
                {
                    Console.Out.WriteLine("Client exception: " + e.Message + " : Blocking = " + client.Blocking);

                }

            }

        }

    }

    }





    Ouput:

    Client exception: A connection attempt failed because the connected party did no
    t properly respond after a period of time, or established connection failed beca
    use connected host has failed to respond : Blocking = True
    Client exception: A non-blocking socket operation could not be completed immedia
    tely : Blocking = True
    Client exception: A non-blocking socket operation could not be completed immedia
    tely : Blocking = True
    .
    .
    .

    Wednesday, November 9, 2005 2:02 AM
  • Thanks
    We will take a look at this tomorrow
    Wednesday, November 9, 2005 4:11 AM
    Moderator
  • First: there are actually 3 exceptions you're getting with your code:
    10054 "An existing connection was forcibly closed by the remote host" (WSAECONNRESET Connection Reset by peer)
    10060 “A connection attempt failed because the connected party did not properly respond after a period of time, or the established connection failed because the connected host has failed to respond.  (WSAETIMEDOUT Connection timed out)
    10035 “A non-blocking socket operation could not be completed immediately”

    The reason: you need to start the server thread first
    Thread serverThread = new Thread(new ThreadStart(Server));
    serverThread.Start();
    Right now only your client is running, it tries to send and receive from server that has not started...

    Second thing: before receiving you should first bind... (this is for both the server and the client, since both of them are issuing send and receive).
    Your code worked with those 2 modifications

    Let me know if this helped
    Mariya


     

    Thursday, November 10, 2005 3:24 AM
    Moderator
  • I don't recall seeing the first exception, but your right on the other accounts. I missed the statement in the Connect routine that says a local endpoint will not be assigned until a send/receive is called. Bind will correct that problem.

    And yes I didn't start the server thread.

    I'm still confused about the final exception. If the socket is a blocking socket, shouldn't an error other than a "Non-blocking socket operation could not be completed immediately." be returned? Shouldn't the call just block on a blocking socket?

    I orginally hoped that this would shed some light on why my application is receiving this error after about 4000 successful send/receive pairs on the client. The posted  (broken) code's exception changed from 10060 to 10035 on the second Receive() call so there was some state change in the socket between Receive() invocations that caused the error code to change. What caused the change? Perhaps it's the same change I'm seeing in my application where about every other Receive() call returns the 10035 exception? Retrying the operation typically succeeds on the first or second retry but as far as I can tell, once this pattern starts, it doesn't stop. It certainly could be caused by something happening on the other end of the socket but 10035 doesn't clue me in to what it might be. 

    So I guess I'm still back at the original question: I have a blocking socket raising the WSAEWOULDBLOCK (10035) error, what causes this?

    - Ray

    Thursday, November 10, 2005 5:16 AM
  • Ray,
    we are still investigating the WSAEWOULDBLOCK (10035) error. We'll keep your posted. For your other application: in order to be able to answer you better for your application we need to know more about it. For instance: are you using asynchronous callls anywhere in your application? Are you using blocking sockets only? Are you always using Connect and Receive for the udp sockets or SendTo/ReceiveFrom?

    In the meantime there are a few other things you may want to consider:
    1) you are assuming your IPAddress is always IPv4, and in some cases it might be IPv6 address.
    static Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    IPAddress addr = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];
    You could either check if the addr is an IPv4 address and then proceed if it is or when creating the socket instead of AddressFamily.InterNetwork use addr.AddressFamily

    2) The other thing is: if you are using asynchronous calls somewhere in your application, then the blocking property has no effect.

    "The Blocking property has no effect on asynchronous methods. If you are sending and receiving data asynchronously and want to block execution, use the ManualResetEvent class..."


    3) The 10060 error in your other application could be due to the ReceiveTimeOut. After the 500ms are over it will forcibly abort the connection. At that point the server/client are no longer synchronized and you start getting this error more often.

    Mariya
    Thursday, November 10, 2005 6:05 PM
    Moderator
  • As a temporary workaround you may want to explicitly set the Blocking property to true right before you call receive.

    client.Blocking =
    true;
    client.Receive(buffer);

    Mariya
    Friday, November 11, 2005 2:04 AM
    Moderator
  • Actually, I just started reseting blocking to true (actually false and then true) but after the failure rather than before the call, and it ran for about 6 hours without hitting WSAEWOULDBLOCK so you might be onto something there. I don't think it has ever ran that long without hitting WSAEWOULDBLOCK.

    A little more about the app:

    - No async calls
    - Only blocking sockets
    - Multiple threads accessing the socket but synchronized (I was able to get a call interupted (WSAEINTR) violation by removing a lock)
    - Only using Connect() and Receive() for packet tranfer
    - Not calling Bind since I don't care what the local endpoint is

    That's off the top of my head. If I come up with more, I'll post again.

    Also, I don't hit 10060, that was just the example code, but I am interested in more detail of when the connection is forcibly aborted. I haven't seen this exception but your comment seems to imply that it can be related to a timeout. I do have Receive() timeout on occasion and I resend the packet but I've never hit 10060.  I'm also setting a new timeout value on every call based on a standard deviation.

    Thanks!
    Ray

    Friday, November 11, 2005 2:19 AM
  • First, let me say you were right about the WSAEWOULDBLOCK exception. Thanks for bringing this to our attention. We will be working on getting this fixed.

    For 10060, what I meant was that you could ge  it due to the receive timing out on a blocking socket.(as was the case with your example code). You can see the socket error codes and descriptions here.
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp

    For 10054 (WSAECONNRESET) you may want to check the MSDN description of recvfrom and see when you get WSAECONNRESET
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/recvfrom_2.asp
    The ideia is that when  there is no UDP listener, the stack receives ICMP port unreachable error and delivers this to the app via WSAECONNRESET. A single send may not be enough to trigger this. The stack does not keep track of every unreachable packet, since you may be sending to different destinations. That’s just too much overhead. Try sending a few packets and then call recv, which should fail with WSAECONNRESET. The design is such that an app isn’t blindly sending packets into a black hole.

    Let me know if this post helped.
    Mariya Atanasova

    Friday, November 11, 2005 11:43 PM
    Moderator
  • Any progress on this? I have a problem with that exception as well with a similar code, and if there is any solution, i would be greatful to see it.
    Saturday, September 2, 2006 1:02 PM
  • Atanas,

    Did you try explicitly setting the blocking property to true as suggested in this thread?

    Mariya

    Wednesday, September 27, 2006 5:45 PM
    Moderator
  • The temporary solution worked. I had the same kind of problem, but on an established TCP connection.

    Thursday, October 5, 2006 12:45 PM
  • Thanks Mariza.  This fixed my problem.

     

    Appreciate the succinct post with sample code.  You helped me enormously.

     

    Robert

    Thursday, May 17, 2007 4:16 PM