How to tell when a Socket has been disconnected

匿名 (未验证) 提交于 2019-12-03 02:50:02

问题:

On the client side I need to know when/if my socket connection has been broken. However the Socket.Connected property always returns true, even after the server side has been disconnected and I've tried sending data through it. Can anyone help me figure out what's going on here. I need to know when a socket has been disconnected.

        Socket serverSocket = null;         TcpListener listener = new TcpListener(1530);         listener.Start();         listener.BeginAcceptSocket(new AsyncCallback(delegate(IAsyncResult result)         {             Debug.WriteLine("ACCEPTING SOCKET CONNECTION");             TcpListener currentListener = (TcpListener)result.AsyncState;             serverSocket = currentListener.EndAcceptSocket(result);         }), listener);           Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);         Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be FALSE, and it is         clientSocket.Connect("localhost", 1530);         Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be TRUE, and it is          Thread.Sleep(1000);         serverSocket.Close();//closing the server socket here         Thread.Sleep(1000);          clientSocket.Send(new byte[0]);//sending data should cause the socket to update its Connected property.         Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be FALSE, but its always TRUE

回答1:

After doing some testing, it appears that the documentation for Socket.Connected is wrong, or at least misleading. clientSocket.Connected will only become false after clientSocket.close() is called. I think this is a throwback to the original C Berkeley sockets API and its terminology. A socket is bound when it has a local address associated with it, and a socket is connected when it has a remote address associated with it. Even though the remote side has closed the connection, the local socket still has the association and so it is still "connected".

However, here is a method that does work:

!(socket.Poll(0, SelectMode.SelectRead) && socket.Available == 0)

It relies on that fact that a closed connection will be marked as readable even though no data is available.

If you want to detect conditions such as broken network cables or computers abruptly being turned off, the situation is a bit more complex. Under those conditions, your computer never receives a packet indicating that the socket has closed. It needs to detect that the remote side has vanished by sending packets and noticing that no response comes back. You can do this at the application level as part of your protocol, or you can use the TCP KeepAlive option. Using TCP Keep Alive from .NET isn't particularly easy; you're probably better off building a keep-alive mechanism into your protocol (alternately, you could ask a separate question for "How do I enable TCP Keep Alive in .NET and set the keep alive interval?").



回答2:

Just write to your socket as normal. You'll know when it's disconnected by the Exception that says your data couldn't be delivered.

If you don't have anything to write...then who cares if it's disconnected? It may be disconnected now, but come back before you need it - why bother tearing it down, and then looping a reconnect until the link is repaired...especially when you didn't have anything to say anyway?

If it bothers you, implement a keep alive in your protocol. Then you'll have something to say every 30 seconds or so.



回答3:

Maybe solution is to send some dummy data through it and check if it times out?



回答4:

I recommend stripping out the higher-level language stuff and explore what happens at the lower-level IO.

The lowest I've explored was while writing isectd (find on sourceforge). Using the select() system call, a descriptor for a closed socket becomes read-ready, and when isectd would attempt the recv() the socket's disconnected state can be confirmed.

As a solution, I recommend not writing your own socket IO and use someone else's middleware. There are lots of good candidates out there. Don't forget to consider simple queuing services as well.

PS. I would have provided URLs to all the above but my reputation (1) doesn't allow it.



回答5:

does the clientSocket.Send() method wait for the packet to either be ack/nack'd?

If not your code is flying onto the next line while socket is still trying to figure out what is going on.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!