Locked The underlying connection was closed

  • Monday, May 21, 2012 2:55 PM
     
      Has Code

    I have an application that runs on a tablet in our warehouse. However, sometimes a warehouseman will walk into a wi-fi "dead zone", and will get an error message "The underlying connection was closed, etc". As this is a situation that I should be coding for, I'm trying to "Catch" the error so I can recover from it. The problem is, that I can't seem to catch the error. According to the error mesage, the error is a System.Net.Sockets.SocketException. So I'm doing the following

            Try
                wsD3 = New D3WebService.D3WebServiceSoapClient("D3WebServiceSoap")
                OipRec = wsD3.ShopTablet_GetOip(tbOrdNo.Text, tbProdPos.Text)
                Me.FillForm(OipRec)
            Catch wEx As System.Net.WebException
                MessageBox.Show(WebErr, "Network error"MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1)
            Catch sEx As System.Net.Sockets.SocketException
                MessageBox.Show(WebErr, "Socket error"MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1)
            Catch ex As Exception
                MessageBox.Show(ex.Message, "Program error message")
            Finally
                wsD3.Close()
            End Try

    But what happens is that instead of the error being caught in the SocketException catch, it's being caught in the general Exception catch. Why should that be?

    If this is not a good method of recovering from walking into a wi-fi dead zone, can anyone give me a better method?

    Thanks

All Replies

  • Monday, May 21, 2012 3:58 PM
     
     

    The code you posted will only fail when you open the connection and not when the connection is closed.  Yo need to capture the close event and use a Callback method to catch the closing option.  Yo have two isues that you need to look at.

    1) The Transfer Protocol is probably TCP.  A TCP connection should automatically reconnect.  but is usually doesn't on Microsoft Windows applications.  There is a bug in the TCP protocol thats been there for over 10 years that shuld be fixed.  Maybe somebody at microsoft will eventully realize this.

    2) Add to your code a Call.EndRecieve method.  The D3WebServiceSoapClient uses the Socket Class and all sockets can be implimented with a Endreceivve() Method.

    http://stackoverflow.com/questions/686618/tcp-client-asynchronous-socket-callback


    jdweng

  • Tuesday, May 22, 2012 7:58 AM
     
     

    Joel are you sure about your answer?? I can't see how either of your points make sense...

    a) What!!!  TCP should reconnect without being asked to do so?  No way.  How it works is, if a two devices can't communicate e.g. if one is off the network or the network is broken, the TCP will do what it is designed to do and keep retrying to send.  But it shouldn't do this forever.  It should retry a number of times and then close the connection and tell the consumer program that there's a problem.  Are you really saying that TCP should auto-magically make a brand new connection then!

    b) Shoomie here is using WebServices are you really saying that ther best solution is to not use WebServices but to instead thrown way all the MSFT WebServices library code and manually create a socket and have to manually open and close sockets and to write the huge amount of code to manually create and parse the WebServices XML??  Surely not.


    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, please vote and/or mark the question answered. Available for contract programming.

  • Tuesday, May 22, 2012 8:06 AM
     
     Answered

    Hi Shoomie

    Can you run your program in Visual Studio, set Debug->Exceptions and put a check in the "Thrown" checkbox for CLR Exceptions.  Now start your program and make the network die just before running the code above.  The VS debugger will now stop the program immediately when any error occurs.  That'll a) show where the exception occurs (is it on New, _GetOip, or even Close) and b) what exception occurs, is it a SocketException, or is it some other exception type with the SocketException as an InnerException?

    BTW as I note in my other response, this is behaving as expected: if TCP keeps retrying to communicate but there's no network for a extended period then it should close the connection and tell the consumer program -- which allows it to take other action based on that.  So this does look like the correct way to handle this.  You might want your program to be able to handle disconnected scenarios however; perhaps when disconnected keeping a list of the updates that can be made once the device is back in the WiFi zone.


    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, please vote and/or mark the question answered. Available for contract programming.

    • Marked As Answer by Shoomie Tuesday, May 22, 2012 2:38 PM
    •  
  • Tuesday, May 22, 2012 12:21 PM
     
     

    Alan: What you said in "a)" doesn't make sense.  If you don't have a connection, then why are you resending a message.  If TCP closes a connection when the idle timeout expires, then when the next message is sent TCP should automatically reconnect before sending data.  Many people havve set the TCP timeouts to infinite because this feature doesn't work on windows applications.

    Also the error Shoomie is getting is occuring when the connection closese.  He only has traps in the code when th econnection is establish.  Shoomie has to add a callback to the close connection event to trap the problem he is lookin for.

    The TCP layer isn't working properly and that is why he is having this problem.  the connection is closing without the user knowing that it closed.  As soon a new message is sent the conection should automatically re-establish itself and it is not.

    I wondering if in the wharehouse the where Shoomie is using his application that in differrentt sections of the whare house they have more than one server each with a different IP address. 


    jdweng

  • Tuesday, May 22, 2012 2:38 PM
     
     

    Alan

    You're a genius! I did as you said, and came up with the following info:

    1) The error was generated on the _GetOip command

    2) The error turned out not to be a SocketException, but a System.ServiceModel.EndpointNotFoundException. When I coded a Catch for that error, I was able to trap it and recover from it.

    Thanks alot for your insights. I also learned about setting those Debug options. I wasn't aware of them. Will be useful in the future.

    BTW, I did test this on the tablet and it works. However, because debuging it on a tablet would have been a hassle, I originally tried the scenario on my development machine by enabling and disabling the network connection as I desired. That worked fine. I then tested it on the tablet just to verify, and it proved correct.

    Thanks again

  • Tuesday, May 22, 2012 4:22 PM
     
     

    Wow Joel!  Sorry I don't have the time to work my way through your message.

    Shoomie's problem is solved and without *any* of the complexity you are suggesting. He catches the exception and can retry later once the device is back in WiFi range.

    TCP is working here exactly as designed. Infinite timeouts: what a disastrous idea. How often would a PC survice before needing a reboot to clear thousands of orphaned connections if TCP was using infinite timeouts. :-(


    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, please vote and/or mark the question answered. Available for contract programming.

  • Tuesday, May 22, 2012 4:33 PM
     
     

    Alan: Have you ever run the Dos command netstat -a to see all the TCP connection.

    What shoomie is really doing is a work around becausse TCP isn't coming up automatically by itself.  Shoomie he is capturing in the exception when the TCP attempting to come back up after is went down.  I was trying to capture the close event which is what Shoomie ask to capture.

    Yes the current solution will work, but is it the BEST solution?  When you get into a DEAD Zone you will never know that you are in a dead zone until you try to send a message and then you will get an exception.  By capturing the close event then you know you are in a dead zone before you try to send the message.


    jdweng