2011-03-04 107 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