On the server side, I'm trying to gracefully close a connected socket. I know the proper sequence of events on the Socket should be:
socket Shutdown with the SocketShutdown.Send option
loop/wait until a socket Receive returns with 0 bytes
socket Close
I have a few questions:
what if Socket.Receive never returns (with 0 bytes)? will we be stuck trying to close the socket forever?
whenever i call Close on the server, the Client always receives "an existing connection was forcibly closed by a remote host" exception on their end. how can i have the client notified of this close "gracefully"?
on the server, if I'm using Async Begin/EndReceive calls, whenever I call Close on the socket, it ALWAYS results in an ObjectDisposedException on the Begin/EndReceive thread. Is there no way to Close a socket without this exception from occurring?
The TCP protocol guarantees the socket will close eventually unless the peer refuses to allow it to close. In which case, you should wait forever or give up, whatever's appropriate.
If you close the socket after receive returns zero, that should not happen. If it is, your code is likely doing something wrong.
You can't release a resource while an asynchronous operation is or might be using it. Rather than calling close, call shutdown. Don't call close until you're 100% finished with the resource.
Related
I know this isn't exactly a bug, but I'm wondering if there is something I can do about it. I have a TCP server serving HTTP requests, and I am using socket keep-alive to act as a heartbeat to detect if the client is still connected to know if I can close their connection as I won't be getting any further requests from them. My issue is that when I close the connection for some other reason (server shutting down or something), the underlying socket keeps sending keep alive packets and remains alive even though I have closed it in code.
This is how I setup the keep alive in code:
// I don't think the specific values here are important, I was just experimenting with it
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, 10);
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, 5);
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveRetryCount, 3);
And then this is how I am closing it:
await socket.DisconnectAsync(false);
socket.Close();
socket.Dispose();
Once I have closed the socket I can see the first two close packets fire off in Wireshark. 5050 port is my server, and 56068 is the Chrome client.
But then Chrome will keep the socket alive for quite a while afterwards rather than just closing it. The socket stays in the FIN_WAIT_2 state for a long time waiting for Chrome to finally finish the close:
Then finally, after a long while, Chrome will send the second half of the close packets, and then the socket is actually closed, and does not appear with netstat -ano any more:
Is there a reason Chrome would be keeping that socket open for so long, and is there anything I can do about it? Maybe this is sort of a non-issue, and I can just ignore it, but it just feels wrong to me that the socket stays open for so long after the server has said "I'm done". Or maybe I have a fundamental misunderstanding of something.
Simply put, is it possible to reuse a socket after a TimedOut exception has been caught? How can I do it?
Long story:
I have 2 threads, both using the same socket. One is sending packets (let's call it thread A) to a remote server while the other (thread B) is listening for confirmation packets of those sent packets. Thread A will pause (with Monitor.Wait) when some condition is met, waiting for a Monitor.Pulse to continue. When thread B receives a packet, it calls Monitor.Pulse and thread A continues to do it's thing...
The problem is that packets can be lost and thread B will wait indefinitely for a packet that won't receive while thread A is waiting for a pulse. The whole program will "block". My first thought was to set a receive timeout and catch the associated exception. When that happens, I call Monitor.Pulse and thread A can continue while thread B will keep waiting for another packet.
But this doesn't work. When the exception is caught, the socket will close and the app will crash when thread A tries to send a new packet, since they are using the same socket.
How can I prevent this behavior?
The problem is that packets can be lost
No they can't. TCP does not lose packets. If you are losing packets you have a bug in your code, or the sender isn't sending them. No problem here yet.
When the exception is caught, the socket will close
No it won't. It will only close when you close it.
and the app will crash when thread A tries to send a new packet, since they are using the same socket.
Only if you closed the socket when you caught the timeout exception. So don't do that.
How can I prevent this behavior?
Don't close the socket when you catch the timeout exception.
TCP Packets cannot be lost (they can but that's on a whole different layer).
If there is a communication error the socket will close.
However if you're using UDP Communications and you've selected a receive timeout, there is no reason you shouldn't be able to try again.
Check This out.
And Read the remarks here.
On the server side, I'm trying to gracefully close a connected socket. I know the proper sequence of events on the Socket should be:
socket Shutdown with the SocketShutdown.Send option
loop/wait until a socket Receive returns with 0 bytes
socket Close
I have a few questions:
what if Socket.Receive never returns (with 0 bytes)? will we be stuck trying to close the socket forever?
whenever i call Close on the server, the Client always receives "an existing connection was forcibly closed by a remote host" exception on their end. how can i have the client notified of this close "gracefully"?
on the server, if I'm using Async Begin/EndReceive calls, whenever I call Close on the socket, it ALWAYS results in an ObjectDisposedException on the Begin/EndReceive thread. Is there no way to Close a socket without this exception from occurring?
The TCP protocol guarantees the socket will close eventually unless the peer refuses to allow it to close. In which case, you should wait forever or give up, whatever's appropriate.
If you close the socket after receive returns zero, that should not happen. If it is, your code is likely doing something wrong.
You can't release a resource while an asynchronous operation is or might be using it. Rather than calling close, call shutdown. Don't call close until you're 100% finished with the resource.
I am writing a C# .NET server application that sends and receives data over Sockets, and I am having some issues if the client application crashes without closing the socket the right way.
I have set the 'receive timeout' to a given value, and I expected the Socket.Receive() to throw an exception after that amount of time. But instead the method just returns 0.
So my question is: Is it possible that the socket is still open if the Socket.Receive() returns 0? Or can I safely assume that it is down?
(Might be a bit tricky to understand. If so, please let me know in the comments)
Nope. It's down if you receive 0.
From MSDN:
If the remote host shuts down the Socket connection with the Shutdown method, and all available data has been received, the Receive method will complete immediately and return zero bytes.
http://msdn.microsoft.com/en-us/library/8s4y8aff.aspx
Your question is a little confused. The Socket is open until you close it. The connection is open until either end closes it. The read side of a connection can be closed by the sender shutting it down for output. So when reading a connection you will receive zero if the peer has either closed his socket or shut it down for output. At that point, your socket is still open, although you should now close it.
It will also return zero if the local application has shutdown the socket for input.
My server/client start a new thread "readerThread()" for reading incoming tcp traffic. This thread blocks on read(). How can i exit this readerThread().
One way is to start another thread which closes the socket when the thread is to be exited so the read would exit. is there a more cleaner/better way to do it.
I misunderstood the question. Here is what I think you should do.
If you created the socket in parent thread, and only use the new thread to read incoming data, then I would suggest calling Socket.Shutdown().This way the Receive methods will return 0 (no bytes read), and you can exit from thread's method. Shutdown will disable send/receive, but if there is any data in buffer that is waiting to be sent/received it will ensure that it is sent/received before closing the socket. Your Receive method will return 0 if you call shutdown while the socket is blocked on Receive, but it will throw a socket exception with Socket error code = Shutdown (or 10058). So be ready to catch and handle it.
If you create the socket in new thread, and its accepting new connections (Socket.Listen() and Socket.Accept) then you can connect with that socket from your parent thread and Send 0 bytes. You can exit new thread when Receive methods returns 0 bytes.
If you are creating the socket in new thread, and it can only a client (Connects with other socket) then this is not a good approach at all. You may have to Abort the thread (not recommended), unless you configure your server to send 0 bytes when you want your client socket to close, but this way your client app will be dependent on server for closing the socket.
If you're using a blocking read() command, you should almost always have another control thread that is in charge of shutting it down and cleaning up the socket.
Typically though, I would use a select() call that times out after 1 second or so to test if there is data to be read, and each timeout cycle checks if a shutdown status flag has been set by another thread.
But if you go with pure blocking, use a control thread as you suggest.
I would use Asnyncronous Socket communication. I wrote an article which demos this on my blog. ou can read here:
http://www.andrewrea.co.uk/blog/2009/06/09/Part1SocketProgrammingWithCJAVACAndActionScript30EstablishingABaseConnectionAndCommunicationWithCServerAndAS3.aspx
Andrew
I'm somewhat puzzled what exactly you are doing: there is no read() method for the Socket class in .NET.
My recommendation is to create a second socket, which is listening on a specific port, and have the thread block in Socket.Select instead. Connecting to that second socket should be taken as a shutdown request (perhaps after proper authentication, e.g. by sending an application password over that socket).
Another way to do it is to send a 0 byte packet to your listening socket from somewhere else in your own application when you want to shut it down.
I've found that's a slightly cleaner approach than closing the coket from another thread since an exception will be thrown by the listening thread if you close the socket on it.