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.
Related
I'd like to write parallel execution module based on Solace. And I use request-reply schema for this.
I have:
Multiple message consumers, which publish messages into the same queue.
Multiple message producers, which read queue and create reply messages.
Message execution time is between 10 seconds to 10 minutes.
Queue access type is non-exclusive (e.g. it does round-robin between all consumers).
Each producer and consumer is asynchronous, e.g. Solace API blocks execution during the connection only.
What I'd like to have: if produces works on the message, it should not receive any other messages. This is extremely important, because some tasks blocks executor for several minutes, however other executors can be free after couple of seconds.
Scheme below can be workable (possible), however blocking code appears below. I'd like to avoid it.
while(true)
{
var inputMessage = flow.ReceiveMsg( /*timeout 1s*/1_000); // <--- blocking code, I'd like to avoid it
flow.Ack(inputMessage.ADMessageId);
var reply = await ProcessMessageAsync(inputMessage); // execute plus handle exceptions
session.SendReply(inputMessage, reply)
}
Messages are only pushed to the consuming applications.
That being said, your desired behavior can be obtained by setting the "max-delivered-unacked-msgs-per-flow" on your queue to 1.
This means that each consumer bound to the queue is only allowed to have 1 outstanding unacknowledged messages.
The next message will be only sent to the consumer after it has acknowledged the message.
Details about this feature can be found here.
Do note that your code snippet does not appear to be valid.
IFlow.ReceiveMsg is only used in transacted sessions, which makes use of ITransactedSession.Commit to acknowledge messages.
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.
I have written a TCPIP server that implements a FileSystemWatcher and fills a queue with data parsed from new files acquired by the FSW.
A single client will connect to this server and ask for data from the queue (no other client will need to connect at any time). If no data exists, the client will wait (1 second) and try again.
Both client and server are written asynchronously - my question is: should the client create a new socket for each transaction (inside the while loop), or just leave the socket open (outside the while loop)?
client.Connect()
while(bCollectData)
{
... communicate ...
Thread.Sleep(1000);
}
client.Shutdown(SocketShutdown.Both);
client.Close();
I would suggest you to leave socket open and even better to block it on the server, so that you didn't have to do Thread.Sleep. When the server will have some data he will send the message to the client.
The code will look something like this
while(bCollectData)
{
_socket.recv(...); //this line will wait for response from server
//... process message and start another wait in the next iteration.
}
using this approach you will get all messages immediately and avoid unneeded messages sent between client and server(the messages which return that server has no data).
I would leave the socket open outside the loop, reconnecting every iteration seems like a waste of resources.
I would not close the socket. Every time you connect you have some handshake.
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.
I recognize this type of question has a long history, but the way I am using this must be the correct '.net way' and yet it does not seem to work.
I have a trivial synchronous IP server daemon that does a simple AcceptSocket, do some stuff, socket.send, socket.shutdown, socket.close. My client is another trivial C# app that does URLDownloadToFile.
What happens is that part of the time URLDownloadToFilefails fails with (0x800C0008) .. thinks its download resource failed.
My server side end sequence is:
socket.Shutdown(Both);
socket.Close();
If I change this to
socket.Disconnect();
socket.Close();
(I open the above with sockopt Linger true, timeout 5 secs)
this works great.
Am I missing something on the Shutdown method.. it sounds like the 'magic bullet' MS wants you to use for gracefully doing an exit that will ultimately send any remaining send data.
Grossly, (and this cannot be right) it appears like the close.. kills any async processing that might be in progress from shutdown().
Any ideas?
Based on Socket.Disconnect
If you need to call Disconnect without first calling Shutdown, you
can set the DontLinger Socket option
to false and specify a nonzero
time-out interval to ensure that data
queued for outgoing transmission is
sent. Disconnect then blocks until the
data is sent or until the specified
time-out expires. If you set
DontLinger to false and specify a zero
time-out interval, Close releases the
connection and automatically discards
outgoing queued data.
Suggests the Shutdown is at best unnecessary...
For reusing the socket use:
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(true);
For force closing use:
socket.Shutdown(SocketShutdown.Both);
socket.Close();