Is it possible to reuse a socket after a TimedOut exception? - c#

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.

Related

How do I close all connections to my server? [duplicate]

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'm using Socket to listen for new connections. How do I break out of synchronous Socket.Accept() method? How do I terminate this call?

I understand, Socket.Accept() is a blocking call, and there is no timeout property for it (like ReceiveTimeout or SendTimeout). So the thread will just keep waiting indefinitely for a new connection to arrive.
So my questions is, how do I terminate this call after a certain point of time. Should I consider closing the listening Socket from some other thread?
Any better ways to do this?
You could use Socket.Poll which allows you to wait for a connection with a timeout. Call it with SelectMode.SelectRead, and if it returns true there is a connection pending that you can accept without blocking.

Will many "UdpClient ReceiveAsync" wait forever?

I have this piece of code to send a command through UdpClient and then wait for a response:
cameraListener = new UdpClient(52381);
cameraSender = new UdpClient();
cameraSender.Connect(endPoint);
int dataSent = await cameraSender.SendAsync(command, command.Length);
UdpReceiveResult result = await cameraListener.ReceiveAsync();
Note: "endPoint" is just a normal IPAddress:port endpoint.
What would happen if the Camera is offline?
Since it is UDP, the SendAsync will send the data correctly but the ReceiveAsync will wait for a response forever. And if those two lines of code (the SendAsync and the ReceiveAsync) executes periodically, will infinite ReceiveAsync wait for a response forever until the system would crash?
Or will they terminate or be terminated by OS at some time? Is it essential to implement a Timer to manually "kill" the UDP socket to terminate the eternal waits?
UDP messages can get lost. This means that your receive can indeed wait forever if the other party does not retry its message. You need a timeout.
Even worse, if you run this code multiple times (with the intention of sending multiple times) you can receive a message that was meant for the other send because with concurrent reads on the same socket it is undefined what read gets what data.
If you just queue up more and more reads without timeout you'll exhaust some resource sooner or later. Don't do that.
Probably, you should have a receive loop that just receives everything it gets and processes it.
Sending can be independent from that.
Even better, use a reliable transport like TCP.

How to Gracefully Close a Socket from the Server

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.

Exiting a thread blocking on TCP read in C#

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.

Categories