【问题标题】:C# Async UDP listener SocketExceptionC# 异步 UDP 监听器 SocketException
【发布时间】:2011-07-09 02:44:00
【问题描述】:

我有一个非常简单的异步 UDP 侦听器,设置为服务,它已经运行了一段时间,但它最近在 SocketException An existing connection was forcibly closed by the remote host 上崩溃了。我有三个问题:

  1. 是什么原因造成的? (我不认为 UDP 套接字有连接)
  2. 如何复制它以进行测试?
  3. 我怎样才能干净地处理异常,让一切都继续工作?

我的代码如下所示:

private Socket udpSock;
private byte[] buffer;
public void Starter(){
    //Setup the socket and message buffer
    udpSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    udpSock.Bind(new IPEndPoint(IPAddress.Any, 12345));
    buffer = new byte[1024];

    //Start listening for a new message.
    EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
    udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);
}

private void DoReceiveFrom(IAsyncResult iar){
    try{
        //Get the received message.
        Socket recvSock = (Socket)iar.AsyncState;
        EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
        int msgLen = recvSock.EndReceiveFrom(iar, ref clientEP);
        byte[] localMsg = new byte[msgLen];
        Array.Copy(buffer, localMsg, msgLen);

        //Start listening for a new message.
        EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
        udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);

        //Handle the received message
        Console.WriteLine("Recieved {0} bytes from {1}:{2}",
                          msgLen,
                          ((IPEndPoint)clientEP).Address,
                          ((IPEndPoint)clientEP).Port);
        //Do other, more interesting, things with the received message.
    } catch (ObjectDisposedException){
        //expected termination exception on a closed socket.
        // ...I'm open to suggestions on a better way of doing this.
    }
}

recvSock.EndReceiveFrom() 行抛出异常。

【问题讨论】:

    标签: c# asynchronous udp socketexception


    【解决方案1】:

    从this forum thread看来,UDP套接字似乎也在接收ICMP消息并在收到时抛出异常。也许这对于低级状态更新很有用,但我觉得它很烦人。

    首先,定义幻数

    public const int SIO_UDP_CONNRESET = -1744830452;
    

    然后设置低级io控制忽略这些消息:

    var client = new UdpClient(endpoint);
    client.Client.IOControl(
        (IOControlCode)SIO_UDP_CONNRESET, 
        new byte[] { 0, 0, 0, 0 }, 
        null
    );
    

    【讨论】:

    • 伟人!嗨,接收 ICMP 消息并在收到它们时抛出异常有同样的问题。这由你的编码技巧解决!
    • @Kyle,我终于有时间全面测试了!这似乎是异常的实际根本原因。作为参考,我最终同时使用了你的答案和 Jim 的答案,这样即使出现异常,监听器也会重新启动。
    • 链接断开。应更改此答案以更新链接或包含链接指向的信息。
    【解决方案2】:

    如果数据包以某种方式被截断或未完全传递,我已经看到了 UDP 错误。至少,我认为就是这样。我一直无法可靠地复制它。

    我建议你抓住SocketException,记录它(如果你愿意的话),然后处理掉那个套接字。然后再次调用Starter:

    catch (SocketException)
    {
        // log error
        udpSock.Close();
        Starter();
    }
    

    【讨论】:

    • 这就是我最终要做的,但我仍然想知道究竟是什么导致了这个异常(即证明你认为是正确的)。
    • @chezy525 我相信这些套接字异常通常是由套接字上的 ICMP“Destination/Port/etc.unreachable”消息引起的。如果你只是在听,你怎么会得到一个,我不确定。只是一个想法。
    • 尝试启用 system.net 跟踪,看看下面发生了什么
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多