Tech Off Thread

17 posts

TcpClient - Test for Disconnected?

Back to Forum: Tech Off
  • User profile image
    phreaks

    Is there somehow to know when a TcpClient has been disconnected?

    I could do this if I were using the asynchronous methods, but I am not.

    I am using synchronous methods because I need to process the data in the same order it was received.

    Ideas?

  • User profile image
    Ion Todirel
  • User profile image
    phreaks

    Ion Todirel said:
    Sorry, I should have been specific.

    That property is unreliable and shouldn't be used.

    MSDN said:

    Because the Connected property only reflects the state of the connection as of the most recent operation, you should attempt to send or receive a message to determine the current state. After the message send fails, this property no longer returns true. Note that this behavior is by design. You cannot reliably test the state of the connection because, in the time between the test and a send/receive, the connection could have been lost. Your code should assume the socket is connected, and gracefully handle failed transmissions.

  • User profile image
    Ion Todirel

    phreaks said:
    Ion Todirel said:
    *snip*

    well, then you don't have other options, I know it's ugly but there is no other way around

  • User profile image
    Minh

    phreaks said:
    Ion Todirel said:
    *snip*

    Sounds like they're saying that the only way to get the latest connected status is try to use it, ie, do a send or receive, then trap for the exception.

  • User profile image
    PerfectPhase

    Minh said:
    phreaks said:
    *snip*
    Sounds like they're saying that the only way to get the latest connected status is try to use it, ie, do a send or receive, then trap for the exception.

    Yep, that's pretty much your best option.  You can enable TCP keepalive onto the socket to dectect a dead socket, but you need to change the defaults from 2 hours via IOControl to be of any real help.

  • User profile image
    evildictait​or

    The problem here is an understanding of how TCP works.


    Basically we have the concept of a packet. This goes from one computer to another. These are wrapped in a protocol called UDP, and these packets are stateless. What TCP does is put a layer on top of this, allowing you to send a "message" which is broken up by the TCP client and sent as UDP packets, before being reassembled at the other client and propagated upwards:

    message                           message out
         |                                          ^
        V                                          |
      TCP                            TCP (server)
        |                                             ^
        V                                              |
      UDP  --(udp packets)------ UDP


    TCP has the additional property that it ensures that if a packet goes missing on the underlying connection (or arrives but is "broken"), it resends it.

    The problem about "Connectedness" is that TCP is therefore not actually "connected" to anything. It "feels" like a pipe that you push things into - this goes into a series of tubes (see what I did there?) and arrives at the other side, but in reality you're actually sending little packets of information.

    So what happens when you're not sending messages? Basically in order to keep the connection "alive", and to check that the connection is "connected", the TCP layer occassionally sends dummy (non-message) UDP packets to the other side, and back again - basically an "I'm still here message".

    The big question then, is what does it "mean" to say two TCP clients are connected? Given that the Internet isn't really a series of tubes, we basically have two ways of working out whether the thing is connected:

    1) Active connection test: Send a message through the TCP client, and swallow it at the other side. If the other side sends a response (i.e. "It arrived!" packets) back, we're still connected. Most computers send back "active disconnect" packets if the other side isn't properly connected so this can be fast if the connection cannot be made, but if the connection just goes down, you actually have to wait for the packets to get there, plus a timeout time to wait to see if you ever get a "they got here" message back. This means active connection testing is upper bounded in time by the timeout length of the TCP connection, a time measured in seconds, not milliseconds.

    2) Passive connection test: This is much faster, but less reliable, and basically it says a connection is "alive" is we recieved any message within the timeout period (including ping/ack requests). Because this is passive, it can report the Connected property immediately, but because it is cached, it may be wrong.

    When Microsoft made the TcpClient / TcpListener / TcpSocket classes they decided that passive connection testing was probably the more commonly used variant of the two, and this is the reason why the Connected property is sometimes wrong.

  • User profile image
    cheong

    evildictaitor said:
    The problem here is an understanding of how TCP works.

    Basically we have the concept of a packet. This goes from one computer to another. These are wrapped in a protocol called UDP, and these packets are stateless. What TCP does is put a layer on top of this, allowing you to send a "message" which is broken up by the TCP client and sent as UDP packets, before being reassembled at the other client and propagated upwards:

    message                           message out
         |                                          ^
        V                                          |
      TCP                            TCP (server)
        |                                             ^
        V                                              |
      UDP  --(udp packets)------ UDP


    TCP has the additional property that it ensures that if a packet goes missing on the underlying connection (or arrives but is "broken"), it resends it.

    The problem about "Connectedness" is that TCP is therefore not actually "connected" to anything. It "feels" like a pipe that you push things into - this goes into a series of tubes (see what I did there?) and arrives at the other side, but in reality you're actually sending little packets of information.

    So what happens when you're not sending messages? Basically in order to keep the connection "alive", and to check that the connection is "connected", the TCP layer occassionally sends dummy (non-message) UDP packets to the other side, and back again - basically an "I'm still here message".

    The big question then, is what does it "mean" to say two TCP clients are connected? Given that the Internet isn't really a series of tubes, we basically have two ways of working out whether the thing is connected:

    1) Active connection test: Send a message through the TCP client, and swallow it at the other side. If the other side sends a response (i.e. "It arrived!" packets) back, we're still connected. Most computers send back "active disconnect" packets if the other side isn't properly connected so this can be fast if the connection cannot be made, but if the connection just goes down, you actually have to wait for the packets to get there, plus a timeout time to wait to see if you ever get a "they got here" message back. This means active connection testing is upper bounded in time by the timeout length of the TCP connection, a time measured in seconds, not milliseconds.

    2) Passive connection test: This is much faster, but less reliable, and basically it says a connection is "alive" is we recieved any message within the timeout period (including ping/ack requests). Because this is passive, it can report the Connected property immediately, but because it is cached, it may be wrong.

    When Microsoft made the TcpClient / TcpListener / TcpSocket classes they decided that passive connection testing was probably the more commonly used variant of the two, and this is the reason why the Connected property is sometimes wrong.
    Actually I think your usage of "UDP" here is quite misleading as UDP is another thing that is not part of TCP/IP. I know you try to use the analogy that Unix Datagrams don't care whether the receipt receive the packets, but perheps you should just use "packets".

    And yes, the only way to ensure TCP/IP channel is "connected" is to send packet and wait for the "ACK" packet of another side.

    Recent Achievement unlocked: Code Avenger Tier 4/6: You see dead program. A lot!
    Last modified
  • User profile image
    phreaks

    cheong said:
    evildictaitor said:
    *snip*
    Actually I think your usage of "UDP" here is quite misleading as UDP is another thing that is not part of TCP/IP. I know you try to use the analogy that Unix Datagrams don't care whether the receipt receive the packets, but perheps you should just use "packets".

    And yes, the only way to ensure TCP/IP channel is "connected" is to send packet and wait for the "ACK" packet of another side.
    That's all good, but the issue how can you test connectivity when you only have control of one end?

    Say, I am just opening a socket, and reading whatever gets pushed, indefinitely.

    How can I figure out if something hiccups?

    I could have a timer, that checks a timestamp of the last read, and if it's greater than some interval, assume the connection died and recycle the socket; but it seems kludgy.

  • User profile image
    spivonious

    phreaks said:
    cheong said:
    *snip*
    That's all good, but the issue how can you test connectivity when you only have control of one end?

    Say, I am just opening a socket, and reading whatever gets pushed, indefinitely.

    How can I figure out if something hiccups?

    I could have a timer, that checks a timestamp of the last read, and if it's greater than some interval, assume the connection died and recycle the socket; but it seems kludgy.

    I'm also curious if there's a better way to do this than a timeout.

  • User profile image
    cheong

    phreaks said:
    cheong said:
    *snip*
    That's all good, but the issue how can you test connectivity when you only have control of one end?

    Say, I am just opening a socket, and reading whatever gets pushed, indefinitely.

    How can I figure out if something hiccups?

    I could have a timer, that checks a timestamp of the last read, and if it's greater than some interval, assume the connection died and recycle the socket; but it seems kludgy.

    Even if you have control on the other end, if the connection is broken, do you have another way to signal the other end to do what you want?

    Even if you want the other end to send back packet to interval, that's just another form of "timeout"...

    Now consider those busy servers that receive thousands/millions of connection a per minute, can the network stand this additional workload of "bookkeeping"?

    IMHO, "Request on demend" is a more appropiate way of doing this...

    Recent Achievement unlocked: Code Avenger Tier 4/6: You see dead program. A lot!
    Last modified
  • User profile image
    phreaks

    cheong said:
    phreaks said:
    *snip*
    Even if you have control on the other end, if the connection is broken, do you have another way to signal the other end to do what you want?

    Even if you want the other end to send back packet to interval, that's just another form of "timeout"...

    Now consider those busy servers that receive thousands/millions of connection a per minute, can the network stand this additional workload of "bookkeeping"?

    IMHO, "Request on demend" is a more appropiate way of doing this...
    Nah, I am getting data all the time, lapse of perhaps 5-6 seconds max during slow periods, otherwise I am constantly receiveing data.

    I don't think it's benificial to keep opening / closing sockets in this scenario.

  • User profile image
    cheong

    phreaks said:
    cheong said:
    *snip*
    Nah, I am getting data all the time, lapse of perhaps 5-6 seconds max during slow periods, otherwise I am constantly receiveing data.

    I don't think it's benificial to keep opening / closing sockets in this scenario.

    No. I mean you should implement your sending function this way.

    1. Send the data using existing connection, catch your exception.
    2. If it is SocketException and the ErrorCode is OPERATION_ABORTED, ENETRESET or others indicating disconnect condition, reopen the client and attempt to resend it. Retry up to 3 times or any theshold you desire.

    I didn't write it anywhere for you to keep closing/opening sockets. Just do what MSDN documentation suggest you to do - send data to determine whether it's closed.

    Recent Achievement unlocked: Code Avenger Tier 4/6: You see dead program. A lot!
    Last modified
  • User profile image
    phreaks

    cheong said:
    phreaks said:
    *snip*

    No. I mean you should implement your sending function this way.

    1. Send the data using existing connection, catch your exception.
    2. If it is SocketException and the ErrorCode is OPERATION_ABORTED, ENETRESET or others indicating disconnect condition, reopen the client and attempt to resend it. Retry up to 3 times or any theshold you desire.

    I didn't write it anywhere for you to keep closing/opening sockets. Just do what MSDN documentation suggest you to do - send data to determine whether it's closed.

    I can't send data - only receive.

    That's part of the contract.

  • User profile image
    captwiggum

    """
    tcp_disconnect.py
    Echo network data test program in python. This program easily translates to C & Java.

    By TCP rules, the only way for a server program to know if a client has disconnected,
    is to try to read from the socket. Specifically, if select() says there is data, but
    recv() returns 0 bytes of data, then this implies the client has disconnected.

    But a server program might want to confirm that a tcp client is still connected without
    reading data. For example, before it performs some task or sends data to the client.
    This program will demonstrate how to detect a TCP client disconnect without reading data.

    The method to do this:
    1) select on socket as poll (no wait)
    2) if no recv data waiting, then client still connected
    3) if recv data waiting, the read one char using PEEK flag
    4) if PEEK data len=0, then client has disconnected, otherwise its connected.
    Note, the peek flag will read data without removing it from tcp queue.

    To see it in action: 0) run this program on one computer 1) from another computer,
    connect via telnet port 12345, 2) type a line of data 3) wait to see it echo,
    4) type another line, 5) disconnect quickly, 6) watch the program will detect the
    disconnect and exit.

    I hope this is helpful to someone. John Masinter, 17-Dec-2008.
    """

    import socket
    import time
    import select

    HOST = ''       # all local interfaces
    PORT = 12345    # port to listen

    # listen for new TCP connections
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((HOST, PORT))
    s.listen(1)
    # accept new conneciton
    conn, addr = s.accept()
    print 'Connected by', addr
    # loop reading/echoing, until client disconnects
    try:
        conn.send("Send me data, and I will echo it back after a short delay.\n")
        while 1:
            data = conn.recv(1024)                          # recv all data queued
            if not data: break                              # client disconnected
            time.sleep(3)                                   # simulate time consuming work
            # below will detect if client disconnects during sleep
            r, w, e = select.select([conn], [], [], 0)      # more data waiting?
            print "select: r=%s w=%s e=%s" % (r,w,e)        # debug output to command line
            if r:                                           # yes, data avail to read.
                t = conn.recv(1024, socket.MSG_PEEK)        # read without remove from queue
                print "peek: len=%d, data=%s" % (len(t),t)  # debug output
                if len(t)==0:                               # length of data peeked 0?
                    print "Client disconnected."            # client disconnected
                    break                                   # quit program
            conn.send("-->"+data)                           # echo only if still connected
    finally:
        conn.close()

  • User profile image
    staceyw

    "That's all good, but the issue how can you test connectivity when you only have control of one end?
    Say, I am just opening a socket, and reading whatever gets pushed, indefinitely.
    How can I figure out if something hiccups?"

    This is a time honored question. You set the read timeout to something reasonable and catch the timeout error.  It is the only way.  Stuff happens on networks, a 30 second timeout may be normal in some cases.  Other times, you may know that should never happen.  Because we can't wait forever,  timeout and retry is the way network clients handle this kind of issue from the beginning of tcp/ip.  If you think about, it is the only way to detect this.  A down remote stack can't send a "I am down" message - because a dead stack can't talk.  Same issue with a down router or any down hw in the path.  In an ironic way, this is part of the brilliance of tcp/ip and why it won.

  • User profile image
    staceyw

    evildictaitor said:
    The problem here is an understanding of how TCP works.

    Basically we have the concept of a packet. This goes from one computer to another. These are wrapped in a protocol called UDP, and these packets are stateless. What TCP does is put a layer on top of this, allowing you to send a "message" which is broken up by the TCP client and sent as UDP packets, before being reassembled at the other client and propagated upwards:

    message                           message out
         |                                          ^
        V                                          |
      TCP                            TCP (server)
        |                                             ^
        V                                              |
      UDP  --(udp packets)------ UDP


    TCP has the additional property that it ensures that if a packet goes missing on the underlying connection (or arrives but is "broken"), it resends it.

    The problem about "Connectedness" is that TCP is therefore not actually "connected" to anything. It "feels" like a pipe that you push things into - this goes into a series of tubes (see what I did there?) and arrives at the other side, but in reality you're actually sending little packets of information.

    So what happens when you're not sending messages? Basically in order to keep the connection "alive", and to check that the connection is "connected", the TCP layer occassionally sends dummy (non-message) UDP packets to the other side, and back again - basically an "I'm still here message".

    The big question then, is what does it "mean" to say two TCP clients are connected? Given that the Internet isn't really a series of tubes, we basically have two ways of working out whether the thing is connected:

    1) Active connection test: Send a message through the TCP client, and swallow it at the other side. If the other side sends a response (i.e. "It arrived!" packets) back, we're still connected. Most computers send back "active disconnect" packets if the other side isn't properly connected so this can be fast if the connection cannot be made, but if the connection just goes down, you actually have to wait for the packets to get there, plus a timeout time to wait to see if you ever get a "they got here" message back. This means active connection testing is upper bounded in time by the timeout length of the TCP connection, a time measured in seconds, not milliseconds.

    2) Passive connection test: This is much faster, but less reliable, and basically it says a connection is "alive" is we recieved any message within the timeout period (including ping/ack requests). Because this is passive, it can report the Connected property immediately, but because it is cached, it may be wrong.

    When Microsoft made the TcpClient / TcpListener / TcpSocket classes they decided that passive connection testing was probably the more commonly used variant of the two, and this is the reason why the Connected property is sometimes wrong.

    "The problem here is an understanding of how TCP works."

    hey evil.  you may want to edit this after reading it again. 

    UDP -> IP - > network (a unreliable Message based protocol)
    TCP -> IP -> network (a reliable Connection based protocol)

    UDP and TCP are completly seperate and unrelated.

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.