2011-03-04 105 views
6

我有一个非常简单的异步UDP侦听器,作为服务设置,它现在一直工作得很好,但它最近在SocketException An existing connection was forcibly closed by the remote host上崩溃。我有三个问题:C#异步UDP侦听器SocketException

  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()行被抛出。

回答

13

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 
); 
+0

伟人!嗨同样的问题接收ICMP消息,并在收到时抛出异常。你的编码技巧解决了这个问题! – Kevan 2013-03-08 13:02:23

+0

@凯尔,我终于完全测试了这个!这似乎是这个例外的真正根源。作为参考,我最终使用了答案和Jim,这样即使有异常,监听器也会重新启动。 – chezy525 2013-07-30 21:12:54

+0

Broken Link。此答案应更改为更新链接或包含链接指向的信息。 – 2014-03-02 02:23:07

2

如果数据包被截断或以其他方式未完全传递,我已经看到UDP的错误。至少,我认为这就是发生了什么。我从来没有能够可靠地复制它。

我建议你赶上SocketException,记录它(如果你想),然后处理该套接字。然后再次调用Starter

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

这是我落得这样做,但我仍想知道究竟是什么引起了这个例外(即证明你认为是正确的)。 – chezy525 2011-03-29 21:34:07

+0

@ chezy525我相信这些套接字例外通常来自您的套接字上的ICMP“Destination/Port/etc。unreachable”消息。如果你只是在听,你会如何得到一个,我不确定。只是一个想法。 – Kongress 2011-06-30 14:37:02

+0

尝试启用system.net跟踪,看看下面会发生什么 – 2012-02-03 08:19:38