locked
Random 10053 SocketException with async networked I/O RRS feed

  • Question

  • Hi,

    I'm searching for hints to solve this annoying error: 10053 SocketException
    "An established connection was aborted by the software in your host machine"

    I'm developing a Load-testing application to simulate 10000 concurrent Internet Explorer clients. I'm using VS 2005 with .NET 2.0 and C# as coding language. A "virtual agent" uses 2 sockets (HTPP 1.1). Server application is running in Tomcat 5.5 and use Ajax-like framework. It is a stable product an is not likely to be the root of my problem. We already have a working application but it is limited to 500 "virtual agent" because it uses 1 thread per client and sync I/O. I decided to use async I/O and thread pool to increase the number of clients.

    I am randomly getting "10053 SocketException", it is not really linked to any specific situation but may happen more easily when server takes more time to answer a request (let's say about 500ms). It can happen with only 1 virtual agent. It usually occurs in the "BeginRead" part of the code pasted at the end of this post, but it has happened during "BeginWrite" too. Server has no load at all (it is 8 Way CPU with HT) and using real IE at that moment gives no problem.

    After reading a lot i removed MacAfee VirusScan v7.1 and Windows XP SP2 firewall but it didn't helped. I also tryed to run the client application on the same machine a server application but it wasn't better.

    To track the problem down i used WireShark and saw that the request is actually sent to the server but i never get a response, i get SocketException instead. I installed wireshark on server too and saw that request arrives to the server too but immediately after i get a [RST, ACK] packet.



    This may means that the socket has been closed server side. But it's strange, this exception is not what i would expect. Why is it possible to send data on a closed socket? I know that it is possible at TCP level but .NET framework should throw you an error. According to RFC i thought that i would get 0 bytes from BeginRead that is much more cleaner than getting an exception. If the socket has been closed i don't understand why host machine has not noticed it. I can see that server machine have sent [FIN, ACK] before on the same TCP channel.

    So here are finally my question :

    1) How can i detect that a connexion has been closed in async I/O ? (I had no error when sending the data, only while reading).


    Thank for reading my long post.

    Here is my code:
            public void StartReading(WebRequest request) {
                if(readBuffer==null)
                    readBuffer = new Byte[ConfigManager.readBufferSize];

                try {
                    request.ParentSocket.networkStream.BeginRead(readBuffer, 0, ConfigManager.readBufferSize, ReadAsyncCallback, request);
                } catch (IOException ioe) {
                    Logger.LogError(name+" IOException in StartReading:BeginRead "+request.Path);
                    ProcessIOException(request, ioe);
                } catch (Exception ex) {
                    throw new WAException("StartReading:" + ex.Message, ex);
                }
            }

            public void AsyncReadHandler(IAsyncResult result) {
                try {

                    WebRequest request = (WebRequest)result.AsyncState;

                    int bytesRead = 0;

                    try {
                        bytesRead = request.ParentSocket.networkStream.EndRead(result);
                    } catch (IOException ioe) {
                        Logger.LogError("IOException While reading (bytesRead=" + bytesRead + ") response to " + request.Path + ioe.Message);
                    }

                    //Getting 0 bytes while reading means connexion has been closed
                    if (bytesRead == 0) {
                        Logger.LogWarn(name + ">EndRead returned 0 bytes, request=" + request.Path + ", socket has been closed, sending again");
                        RecreateSocketAndSend(request);
                        return;
                    }

                } catch (Exception ex) {
                    Logger.LogError(name + ">AsyncReadHandler: Exception:" + ex.Message);
                    throw new WAException(name + ">AsyncReadHandler: Exception(" + ex.Message + ") Path=" + ((WebRequest)result.AsyncState).Path, ex);
                }
            }
    Tuesday, January 16, 2007 7:00 PM

Answers

  • I finally found a good solution, i'm switching socket to non blocking mode and try to read 0 bytes. If 0 bytes are returned and SocketError = succes then i know that socket has been closed server side. If the connection is still up, SocketError = WouldBlock. The interesting thing is that in both cases results are very fast to get.

    I checked with wireshark and no packet is sent, this is a good thing for performance. Other solutions i found are relying on timeouts and are rather slow even when connection is still up. I think this is a fast way to detect clean disconnection, this may not work if "FIN, ACK" packet is not received by client.

    Here id a piece of my code, i hope this will help.

                        bool previousMode = socket.Blocking;
                        socket.Client.Blocking = false;
                        SocketError se;
                        int bytesRead = socket.Receive(new byte[0], 0, 0, SocketFlags.Peek, out se);
                        socket.Blocking = previousMode;

                        if ((se == SocketError.Success) && (bytesRead == 0)) {
                            Logger.LogDebug(" isConnected = false");
                        }
    Thursday, January 18, 2007 10:07 AM