Where is UdpClient.CancelReceive?

I implement a simple LAN discovery protocol, so I call UdpClient.Send and then UdpClient.BeginReceive. If more than one response is expected, I call UdpClient.BeginReceive at the end of the callback. Something like that:

UdpClient client = new UdpClient(AddressFamily.InterNetwork); client.EnableBroadcast = true; client.Send(request, request.Length, broadcastEndPoint); client.BeginReceive(Callback, client); 

... and then in Callback :

 void Callback(IAsyncResult ar) { UdpClient client = (UdpClient)ar.AsyncState; IPEndPoint remoteEndPoint = null; byte[] response = client.EndReceive(ar, ref remoteEndPoint); // Do something with response client.BeginReceive(Callback, client); } 

My problem is that my main loop calls client.Close while receiving is still client.Close . The receiving completes, and then my next call to BeginReceive raises an exception: System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host

Why doesn't UdpClient have a CancelReceive method? What can I do instead?

+4
source share
2 answers

Using the isClosing flag to notify a callback function that is not available to UdpClient is not the right solution. The callback is executed in another thread, there is always a chance that the connection will be closed after checking the "isClosing" flag and before calling "BeginReceive" (or "EndReceive").

Although this is not a clean design, Microsoft seems to recommend simply catching the appropriate exceptions to find that the socket is no longer available. This is not documented for BeginReceive, but documented for a similar BeginConnect function :

To cancel a pending call to the BeginConnect () method, close the Connector. When the Close () method is called asynchronously, an operation is performed, the callback provided by the BeginConnect () method. A subsequent call to the EndConnect (IAsyncResult) method will throw an ObjectDisposedException to indicate that the operation has been canceled.

So a sample code would look like this:

 void Callback(IAsyncResult ar) { try { UdpClient client = (UdpClient)ar.AsyncState; IPEndPoint remoteEndPoint = null; byte[] response = client.EndReceive(ar, ref remoteEndPoint); // Do something with response client.BeginReceive(Callback, client); } catch (SocketException e) { // Oups, connection was closed } catch (ObjectDisposedException e) { // Oups, client was disposed } } 
+3
source

Instead, or to overcome this exception, create a bool and set it before issuing the close command, use this bool to check the callback

like this

 bool isClosing=false; void Callback(IAsyncResult ar) { if(isClosing) return; } 

set bool isClosing before issuing a close command

+6
source

All Articles