locked
EXCEPTION: "An existing connection was forcibly closed by the remote host"

    Question

  • Hey all,

    I have an asynchronous socket server. Each connection is in it's own thread, and when receiving a message and executing the function associated to that message, there is a try catch. So formatting problems as well as graceful disconnections are handled through that.

    Now, I'm getting an unhandled exception that crashes the server:
    "An existing connection was forcibly closed by the remote host"

    Checking the log file associated to the application, some users can cause that to happen, but they're disconnected and cleaned up via the Try Catch, so there's an exception that is not being handled that is causing it to crash the server. With this type of setup, what should I look out for that would cause this? Network problems? Is this possibly unrelated to the server?

    If it's any consolation, the server never crashed when I had about 70 simultaneous users, but now it has now that there are close to 400 users. I don't know if that's related/unrelated, but just want to try and figure out what causes this unhandled exception:

    "An existing connection was forcibly closed by the remote host"

    On the socket server itself (or maybe one of my timers?).

    Maybe it's network related.

    Thanks!
    -Steve
    Monday, April 02, 2007 12:25 AM

Answers

  • There are different things that can cause this error: for example the server may not have sufficient backlog to process all the users or it may have an implemetted a timeout - i.e. if a user is idle for a certain period of time it may close the connection. Or it could be network problems. Or it could be your code. What you should do is catch the exception then close the socket, open a new one resend the message

     

    Mariya

    Monday, April 02, 2007 2:21 PM
    Moderator

All replies

  • There are different things that can cause this error: for example the server may not have sufficient backlog to process all the users or it may have an implemetted a timeout - i.e. if a user is idle for a certain period of time it may close the connection. Or it could be network problems. Or it could be your code. What you should do is catch the exception then close the socket, open a new one resend the message

     

    Mariya

    Monday, April 02, 2007 2:21 PM
    Moderator
  • Thanks!
     
    Do you think this could be happening on a connect request? Here is the code (it's not in a Try/Catch):
    Code Snippet
     

    Public Sub OnConnectRequest(ByVal ar As IAsyncResult)

    Dim listener As Socket = CType(ar.AsyncState, Socket)

    Dim handler As Socket = listener.EndAccept(ar)

    Dim newClient As New Client(handler, DateTime.Now)

    AddHandler newClient.LineReceived, AddressOf OnUserLineReceived

    AddHandler newClient.ErrorReceived, AddressOf OnUserErrorReceived

    newClient.Sock.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, 1)

    newClient.Sock.IOControl(IOControlCode.KeepAliveValues, inValue, outValue)

    SyncLock clients

    clients.Add(newClient)

    End SyncLock

    'Console.WriteLine("Client {0}, joined at " & DateTime.Now.ToString("G"), newClient.Sock.RemoteEndPoint.ToString)

    'Allow more connections

    'Keep in mind this can be placed in the initial thread with an infinite loop, but this allows

    'the garbage collection and disconnection to happen immediately

    listener.BeginAccept(New AsyncCallback(AddressOf OnConnectRequest), listener)

    End Sub

     

    All the receiving for each user is in a Try/Catch, and any problems would cause them to disconnect, not the server. So, curious why that error would occur and if it could occur in the code above.

    Monday, April 02, 2007 3:39 PM
  • Weird, my post from before isn't posting.
    Monday, April 02, 2007 6:32 PM
  • Yes, socket exceptions can happen in connect too. For example when you're trying to connect and at the same time the server is closing the connection, or your network goes down and you connectivity, or the server loses connectivity, or whatever - there are a lot of things that can cause an exception. You shouldn't assume that you won't get an exception. You should handle all those socket exceptions.

     

    Mariya

    Tuesday, April 03, 2007 12:42 AM
    Moderator
  • Should I throw the above code in a try/catch? Would that fix that issue, and only catch that specific exception?

    It seems to be crashing it every so often with a lot of users. Before I had the backlog set at 10, and with 400+ users, it would disconnect after a few hours. I set it at 30, and with 400+ users, it would disconnect still. Not sure if there's a correlation, because it still seems the same in regards to that. Same exception, though, above.
    Thursday, April 05, 2007 3:47 AM
  • Yes, put it in try catch, catch the specific expecition and handle it and resend the request. Then catch all the other exceptions you might get and handle them as well. I think there was some limit to the backlog you could put, depending on the OS. You could always put larger but it will have no effect. I'll have to double check that

     

    Mariya

    Thursday, April 05, 2007 5:56 PM
    Moderator
  • Thanks!
     
    Which portion of the code should the Try/Catch go around above? I still want it to accept connections after the exception is caught. I'd imagine the try/catch would go around this:
     

    Code Snippet

    Dim listener As Socket = CType(ar.AsyncState, Socket)

    Dim handler As Socket = listener.EndAccept(ar)

    Dim newClient As New Client(handler, DateTime.Now)

    AddHandler newClient.LineReceived, AddressOf OnUserLineReceived

    AddHandler newClient.ErrorReceived, AddressOf OnUserErrorReceived

    newClient.Sock.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, 1)

    newClient.Sock.IOControl(IOControlCode.KeepAliveValues, inValue, outValue)

    SyncLock clients

    clients.Add(newClient)

    End SyncLock

     

     
    And then leave the listener.BeginAccept in the Finally statement with a callback back to the OnConnectRequest. Does that make sense? O.O
     
    Thanks again for your help. Smile
    -Steve
    Thursday, April 05, 2007 10:22 PM
  • So I went ahead and did this:

    Public Sub OnConnectRequest(ByVal ar As IAsyncResult)

    Dim listener As Socket = CType(ar.AsyncState, Socket)


    Try

    Dim handler As Socket = listener.EndAccept(ar)

    Dim newClient As New Client(handler, DateTime.Now)

    AddHandler newClient.LineReceived, AddressOf OnUserLineReceived

    AddHandler newClient.ErrorReceived, AddressOf OnUserErrorReceived

    newClient.Sock.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, 1)

    newClient.Sock.IOControl(IOControlCode.KeepAliveValues, inValue, outValue)

    SyncLock clients

    clients.Add(newClient)

    End SyncLock

    'Console.WriteLine("Client {0}, joined at " & DateTime.Now.ToString("G"), newClient.Sock.RemoteEndPoint.ToString)

    'Allow more connections

    'Keep in mind this can be placed in the initial thread with an infinite loop, but this allows

    'the garbage collection and disconnection to happen immediately

    Catch

    Finally

    listener.BeginAccept(New AsyncCallback(AddressOf OnConnectRequest), listener)

    End Try

    End Sub


    However, the server still crashes with this exception that is somehow not being handled:
    "An existing connection was forcibly closed by the remote host"

    Where should I look for this problem?

    Keep in mind, in my message receive function, it's wrapped in a Try Catch, so if a user throws an exception, they're disconnected. Outside of that, where should I be looking for this exception?
    Thursday, April 12, 2007 12:19 AM
  • This is where you're getting the exception:

     

    Finally

    listener.BeginAccept(New AsyncCallback(AddressOf OnConnectRequest), listener)

     

    When it throws you're not catching the exception

     

    Mariya

    Friday, April 13, 2007 5:29 PM
    Moderator
  • Interesting! How should I handle this?
    Saturday, April 14, 2007 3:14 PM
  • Isn't it obvious? Put this same line in try-catch as well...

     

    Mariya

    Wednesday, April 18, 2007 1:00 AM
    Moderator
  • That's my first reaction, but if it throws an exception, it will no longer accept connections, correct? In this case, does this line need to be in the Try statement as well as the Finally?
    Wednesday, April 18, 2007 3:47 PM
  • This is more of a best programing practices question and there are more adequate forums for that (You can search http://www.microsoft.com/community).

    As a general guideline you only do cleanup and other stuff that you require to execute your code corectly, but if generally code that is not supposed to throw. That is unless you do additional handling outside of this try catch but in your case you do not.

     

    Mariya 

    Wednesday, April 18, 2007 6:17 PM
    Moderator
  • Anywhere else I do proper cleanup when an exception is thrown, but this just seems like something that I can't cleanup being that I need to continue accepting connections, or at the very least delay the acceptance of connections until it's no longer throwing exceptions.
    Wednesday, April 18, 2007 9:01 PM
  • But once you get an exception on that Socket you cannot continue to receive on the same one. What you need to do is close that socket, and open a new one that will accept connections for you. You cannot use the old one (you can, but this is not guarantted to work)

     

    Mariya

    Thursday, April 19, 2007 5:26 PM
    Moderator
  • Interesting.
     
    In your experience, the previous connections that were connected to that socket, will they become disconnected? I'd imagine in the event that I can no longer connect to that socket, I'd have to open another port to listen to and allow connections in on that port.
     
    I'm not sure if this is possible (most likely not), but I'd like on this situation to have those users remain connected before the exception being thrown, and have new users connect to the same port as the socket that threw an exception.
     
    Doesn't sound possible, though.
    Wednesday, April 25, 2007 9:02 PM