Question

I am using the C# UdpClient class to to UDP networking. There is one UdpClient object, bound to a fixed local port, but not to any remote endpoint, because it needs to be able to send/receive to/from multiple different endpoints.

I have two threads: One for sending, one for receiving. Now, when I send data to an endpoint that exists, but doesn't listen on that port, I expect a SocketException. And I do get one. Unfortunately, it is not my Send call that returns the exception, but the Receive call. So on my sending thread, I send data to an "invalid" endpoint, and my receiving thread gets the exception. Unfortunately, at that point, I have of course no idea what endpoint caused that exception to happen.

Storing the endpoint before sending, then accessing that in the receiving thread is just a race condition error waiting to happen.

Unfortunately, the SocketException does not give me the endpoint that caused the error.

Any ideas? Is it somehow possible to make the exception be thrown on the sending thread?

Help is greatly appreciated.

Was it helpful?

Solution

When you send() a UDP packet, it goes out on the wire and effectively disappears. You should not assume that you will get any feedback at all.

Sometimes, if there is no listener at the destination, the destination might be kind enough to send back an ICMP_UNREACH_PORT message. The routers in between then might be kind enough to deliver that message to your operating system. If that happens, it will be long after your original send() call returned. For ICMP_UNREACH_PORT, the OS typically caches it and reports an error the next time yo do a send() to the same destination. Other ICMP messages (you didn't mention which exception you are getting) could affect other calls.

So the bottom line is that there's no telling when, or if, UDP errors will be reported. It depends on a lot of variables. So be prepared to handle exceptions on any call, and be prepared for packets to just disappear without any error reported.

OTHER TIPS

I think this is expected behavior for UDP. A UDP send() is not a blocking operation, so it won't wait for a potential error. (Not to mention the fact that you can't rely on the error messages being reliably received when sending to an active host with a closed port - it could be firewalled, rate-limited or otherwise dropped due to congestion, etc.)

You can connect() the UDP socket to a specific remote endpoint, which would allocate a unique port number and allow the OS to [most likely] distinguish errors from that specific endpoint from any other random host. But again, you should not rely on the ability to handle these errors.

It's too bad there isn't more information in the exception. This seems like an oversight in the way .NET handles UDP sockets. According to the documentation, you need to check the exception's ErrorCode and handle the error appropriately. (which, in your case, could likely mean ignoring the error.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top