简体   繁体   中英

How to efficiently determine the status of a socket in C#?

I have a server that receives data from a client and I want to be able to determine whether the socket is still connected or not.

I am using the following function to determine the status ( source ):

bool SocketConnected(Socket s)
{
    bool part1 = s.Poll(1000, SelectMode.SelectRead);
    bool part2 = (s.Available == 0);
    if (part1 && part2)
        return false;
    else
        return true;
}

However, when the RTT (between Server/Client) is high (~300ms) and varies (+- 60ms), my app "crashes". From debugging I have found out that it is due to the fact that the socket is identified as not connected (SocketConnected() returns false). I know though, that the socket is still connected as I can see the client streaming the content requested from the server, and the server receiving data as captured by the Wireshark.

Should I increase the time for Poll (but I do not want to block other operations) or to use the Socket.Connected Property along with the SocketConnected()? What is the most efficient way to determine the status of the socket in volatile environments?

Unfortunately, the question and answers you've found and referenced is chock-full of terrible advice, and has nothing really constructive to say on the question. Connection-oriented protocols like TCP are specifically designed to defer errors as long as possible, to accommodate potential intermittent transport problems (network cable is unplugged, wireless connection gets reset, whatever) as much as can be done, to minimize the impact of those problems on the actual connection.

Every answer on the referenced question undermines this general strategy, or fails to address the question in a useful way, or both.

The only correct way to deal with this type of scenario is to assume that the socket is in the connection state you expect it to be (based on your own code's operation), while making sure your code has exception handling at every appropriate point of use of the socket. There is no other way.

You can look at the Connected property, but that won't tell you anything useful. The socket could transition to an unconnected state a nanosecond after you checked the property. You should also not be using "select"-based methods like Poll() , as these are inefficient and don't scale with the number of connections.

Every networked program can successfully use asynchronous I/O. If the program has a GUI (eg Winforms, WPF, etc.), then you can even do so while still doing all of your actual data handling in the UI thread (which gives you the luxury of not worrying so much about multithreading issues…using the modern async / await idiom would be preferable, but you can also just use the "old-school" techniques like Control.BeginInvoke() and Dispatcher.InvokeAsync() ).

So, following those guidelines, the only time that the connectedness of the socket will change state in any meaningful, interesting way is when that happens intentionally, which then is detected through normal handling of graceful closure, ie with a read operation completing with zero bytes as the result, or when it happens due to an error, in which case your exception handling will detect the unexpectedly-disconnected state.

You cannot successfully write defect-free network I/O code without proper exception handling, so it only makes sense to rely on that exception handling for all exceptional cases.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM