How can I check whether a (TCP) socket is (dis)connected in C#?

后端 未结 4 986
南笙
南笙 2020-12-04 10:19

How should I check a (TCP) socket to find out whether it is connected?

I have read about the Socket.Connected property in MSDN, but it says it only show

相关标签:
4条回答
  • 2020-12-04 10:56

    "If you need to determine the current state of the connection, make a nonblocking, zero-byte Send call. If the call returns successfully or throws a WAEWOULDBLOCK error code (10035), then the socket is still connected; otherwise, the socket is no longer connected." -- unfortunately, it doesn't even work!

    mySocket.Blocking = false;
    byte[] buffer = new byte[1];
    int iSent = mySocket.Send(buffer, 0, SocketFlags.None);
    bConnected = mySocket.Connected;
    

    bConnected always ends up as true, and the call always returns successfully, even though the Ethernet cable has been unplugged.

    Moreover, and unfortunately == sending any actual data doesn't detect the broken connection, either.

    buffer[0] = 0xff ;
    int iSent = mySocket.Send(buffer, 1, SocketFlags.None);
    

    repeatedly returns 1, as if if had actually sent something. While the device in question isn't even connected any more.

    0 讨论(0)
  • 2020-12-04 10:57

    I don't really understand his statement about calling Receive() to make sure that the remote endpoint has actually received all the data I sent.

    The post by @PeteDuniho isn't about establishing the state of the connection, it is about terminating the connection in such a way that you know when the peer has received all your data.

    (Do sockets block receiving until the sending buffer is empty?)

    No, but if you shutdown the socket and then read until EOS, you are waiting for the peer to read all the data until he gets EOS and then closes the socket. So you have a guarantee that all the data has got into the peer application.

    0 讨论(0)
  • 2020-12-04 11:00

    Typically one would use the Socket.Select method to determine the state of a set of sockets (Socket.Poll for a single socket).

    Both of these methods allow you to query a socket's state. Now, assuming that you have tracked that the socket connected in the first place then you would typically call Select/Poll on the socket before attempting a read. If Select/Poll indicate that the socket is readable this tells you that:

    • Either the socket has data available top read in which case Receive will return the data available to read.
    • The socket socket has been closed, in which case when you call Receive 0 bytes will be returned immediately (i.e. If Select/Poll indicate that the socket is readable and you call Receive but it returns immediately with 0 bytes then you know that the connection has either been Closed, Reset or Terminated.

    Personally I've never used Poll - I've always used Select but MSDN seems to suggest that Poll is pretty much the same as Select but for single sockets.

    I'll also add that in most cases using Select is the most efficient and best way of handling Socket connections.

    0 讨论(0)
  • 2020-12-04 11:05

    Death of a socket changes its behavior in several ways, so these methods are both valid :)

    With both methods you actually check those parts of the socket's behavior that change after disconnection.

    I don't really understand his statement about calling Receive() to make sure that the remote endpoint has actually received all the data I sent. (Do sockets block receiving until the sending buffer is empty?)

    TCP is reliable protocol, that means that every packet you send must be acknowledged. Acknowledgement implies sending the packets with ACK bit set. These packets may or may not contain additional (payload) data.

    When the socket is connected, Receive() will block until the socket receives a packet with non-empty payload. But when the socket is disconnected, Receive() will return as soon as the last ACK packet arrives.

    Calling Receive() ensures that you either receive that last ACK packet from your remote endpoint or a disconnect timeout occurs and you will be able to receive nothing more on this socket.

    The example on the same page shows how to do it. (I wonder why does it allocate a 1-byte array, even though it calls Send with 0 length?) But a post by Ian Griffiths says that I should read from the socket, not send through it.

    When send()ing to a socket, you actually try to append some data to the end of the socket queue. Is there is some place left in the buffer, then your Send() returns instantly, if not, the Send() blocks until there is some place.

    When the socket is in disconnected state, TCP/IP stack prevents all further operations with the buffer, that's why Send() returns an error.

    Send() implements a basic pointer check, this means it fails when a NULL pointer is passed to it. You may probably pass any non-null constant as a pointer, but you better allocate 1 byte instead of making the constant up — just in case.


    You may use any method you like, as none of them is resource consuming. As long as they are used for socket connection checking, they are identical.

    As for me, I would prefer Receive(), as this is what you normally run in a cycle and wait for. You get a non-zero from Receive(), you process data; you get a zero, you process disconnection.

    0 讨论(0)
提交回复
热议问题