UdpClient.CancelReceive在哪里?

时间:2009-05-08 14:35:21

标签: .net sockets

我正在实现一个简单的本地网络发现协议,所以我调用UdpClient.Send然后调用UdpClient.BeginReceive。如果有多个响应挂起,我会在回调结束时调用UdpClient.BeginReceive。像这样:

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

...然后在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);
}

我的问题是我的主循环调用client.Close,而仍有待处理的接收。接收完成,然后我对BeginReceive的下一次调用抛出异常:System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host

为什么UdpClient没有CancelReceive方法?我该怎么做呢?

2 个答案:

答案 0 :(得分:6)

相反或要克服此异常创建bool并在发出close命令之前设置它,使用该bool检入回调

像这样

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

在发出关闭命令

之前设置bool isClosing

答案 1 :(得分:3)

使用“isClosing”标志通知回调函数UdpClient不再可用不是一个合适的解决方案。回调在不同的线程中执行,在“isClosing”标志检查之后和“BeginReceive”(或“EndReceive”)调用之前总是有可能关闭连接。

即使这不是一个干净的设计,微软似乎建议只捕获相应的异常,以检测套接字不再可用。 “BeginReceive”没有记录,但那是documented for the similar function "BeginConnect"

  

要取消对BeginConnect()方法的挂起调用,请关闭   插座。在异步时调用Close()方法时   操作正在进行中,提供给BeginConnect()的回调   方法被调用。随后调用EndConnect(IAsyncResult)   方法将抛出一个ObjectDisposedException来指示   操作已被取消。

因此,示例代码如下所示:

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
    }
}