2012-08-03 65 views
3

我有一個C#應用程序可以從遠程主機接收UDP數據。我發現有時候我的套接字沒有收到任何東西,我似乎也找不到任何線索爲什麼! Wireshark告訴我我的數據正在從遠程設備正確發送。我似乎不明白爲什麼有時候我可以收到罰款,有時我不能。UDP有時無法接收任何東西

我沒有得到任何異常,但OnRecieve不會被調用

這裏是我的情況下,代碼可以幫助:

class cUdpRx 
{ 
    private Thread rxThread = null; 
    private Socket UdpSocket; 
    private IPEndPoint localEp; 
    byte[] byData; 
    //rxbytes event 
    public delegate void OnRxBytesEventHandler(byte[] rxBuf); 
    public event OnRxBytesEventHandler OnRxBytesEvent; 



    /// <summary> 
    /// Creates the udp socket 
    /// </summary> 
    /// <param name="Port"></param> 
    /// <returns></returns> 
    public bool CreateSocket(int Port) 
    { 
     try 
     { 
      byData = new byte[1500]; //create our buffer 
      UdpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 
      UdpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 
      localEp = new IPEndPoint(IPAddress.Any,Port); 
      UdpSocket.Bind(localEp); 
      UdpSocket.BeginReceive(byData,0,byData.Length, SocketFlags.None, new AsyncCallback(OnRecieve), UdpSocket); 

      return true; //seemed to work ok 
     } 
     catch 
     { 
      Dispose(); 
      return false; //something went wrong, abort 
     } 
    } 

    private void OnRecieve(IAsyncResult iar) 
    { 
     byte[] rxData; 
     int nBytesRec = 0; 
     Socket socket = (Socket)iar.AsyncState; 
     try //in case something else has already disposed of the socket 
     { 
      nBytesRec = socket.EndReceive(iar); 
     } 
     catch 
     { 
      Debug.WriteLine("cant access udp rx socket"); 
     } 
     try 
     { 
      if (nBytesRec > 0) 
      { 
       rxData = new byte[nBytesRec]; 
       Array.Copy(byData, rxData, nBytesRec); //copy exact data into new array 
       OnRxBytesEvent(rxData); 
      } 
      if(!killThreads) 
       UdpSocket.BeginReceive(byData, 0, byData.Length, SocketFlags.None, new AsyncCallback(OnRecieve), UdpSocket); 
     } 
     catch(SocketException se) 
     { 
      Debug.WriteLine(se.ToString()); 
     } 
    } 

任何幫助將是非常讚賞,因爲它從前進阻止我與我的項目。謝謝

UPDATE 它似乎使用IPAdress.any是問題。如果我改變:

localEp = new IPEndPoint(IPAddress.Any,Port); 

localEp = new IPEndPoint(IPAddress.Parse("192.168.0.33"),Port); 

其中192.168.0.33是我的電腦的IP地址,接收數據每次。 任何人都可以解釋爲什麼? 使用IPAddress.any和從無線和有線連接接收都非常有用。 IPAddress.any等同於0.0.0.0,根據MSDN它應該在所有網絡接口上接收。

+2

你知道UDP並不能保證數據包像TCP那樣到達嗎?您可能會看到連接不穩定的影響。 – Dervall 2012-08-03 09:04:55

+2

我知道,但如果wireshark看到數據包,它至少意味着NIC正在接收它們。我要麼收到的數據很好,要麼根本沒有。我還想補充一點,我在OnRecieve中使用兩個try/catch可能看起來很奇怪,但我當時正在調試一些東西,所以試圖忽略它。 – gcb 2012-08-03 09:08:05

回答

1

這種問題的通常原因是處理數據包速度不夠快。它們填充套接字接收緩衝區並且內核開始丟棄它們。

增加套接字receive buffer size以適應流量突發。 從快速插槽讀取路徑中移除所有非必需的東西。 考慮簡單的迭代方法波紋管,而不是針對線程池的工作:

rxData = new byte[nBytesRec]; 

while (!time_to_stop) { 
    int len = socket.Receive(rxData); 
    OnRxBytesEvent(rxData, len); 
} 

你的代碼中的註釋提到組播。請注意,您需要爲此添加明確的group membership,以及您在接口上加入組播組的事實(顯式地或通過路由表決定),因此如果要在兩個接口上監聽組播數據,則需要兩個套接字。

+1

我在我的網絡協議中有一些流量控制,所以過度填充接收緩衝區是不可能的。提到多重鑄造是由於從別處複製代碼 - 我很糟糕。這個問題似乎與使用Ipadress.any – gcb 2012-08-03 18:06:06

+0

流量控制,噢,我的......「不可能」是一個相當強大的聲明。重新檢查你的假設。 「INADDR_ANY」可能與真正的問題無關。 – 2012-08-03 18:23:03

+0

我沒有做出任何假設。當我綁定到計算機的IP地址而不是使用IPAddress.Any它的作品。另外,我可以看到wireshark上發生的事情 - 就像我在原始問題中所說的那樣。 – gcb 2012-08-03 20:46:27

0

我剛剛得到同樣的問題,並通過設置timeTolive解決大數據問題。

_client = new UdpClient(); 
_client.Client.Bind(new IPEndPoint(IPAddress.Any, targetURI.Port)); 
_client.JoinMulticastGroup(IPAddress.Parse(targetURI.Host) , 250); 
  • 傳輸TimeToLive = 250,它的工作原理。
  • timeToLive = 50,作品或不作品交替發生。
  • timeToLive =無或0,不起作用。