簡體   English   中英

UDP 客戶端 - 接收排隊的數據包

[英]UDP Client - Reception of enqueued packets

我正在開發一個 UDP 客戶端 PC 應用程序。 它應該從 4 個以上的設備接收 UDP 數據報。
系統的行為方式如下:

  • 多個設備通過固定端口 (11000) 上的 UDP 廣播相互通信,形成一個沒有連接到互聯網的個人區域網絡。
  • PC 應用程序在連接到同一網絡的計算機上執行。
  • PC 應用程序偵聽 11000 端口上的 UDP 廣播以發現設備。
  • 當從 PC 應用程序接收到特定命令時,該設備進入不同的執行模式,而其他設備繼續廣播它們的數據包。
  • 當個人區域網絡中只有一個設備時,這會以期望的方式運行。

當網絡中有兩個或更多設備時,我面臨一個奇怪的問題,例如:

  • 我使用發現的設備列表將endPoint設置為所需設備的所需 IP 地址和端口。
  • 我打電話給myUDP.Receive(ref endPoint); 接收UDP數據報

這將返回由網絡中第二個設備廣播的數據報,而不是從我試圖與之通信的設備返回響應。 我已經使用 Wireshark 驗證了響應是從設備發送的。

我嘗試循環有限次以獲取所需的數據報。

// Some code which initializes the endPoint with desired IP Address and Port
...
// Some code which sends the data
...
// Some code which sets the IP Address of the device from which the response is expected
selectedIPAddress = IPAddress.Parse(labelIPAddressSettings.Text.Trim());
copyendPoint = endPoint;
// Listen to response
do
{
    rexdDatagram = myUDP.Receive(ref endPoint);
    if (endPoint.Address != selectedIPAddress)
    {
        // This datagram is not from the desired device
        // Restore to the desired endpoint
        endPoint = copyendPoint;
        // Not sure if there is way to discard this enqueued datagram
    }
    
    i_timeout = i_timeout + 1;
    if (i_timeout == 10)
    {
        // Datagram from the desired device has not been received 
        break;
    }
    // Not sure if the thread needs to sleep, debugging..
    Thread.Sleep(1000);
} while (1);

問題:我的代碼在入隊數據報中循環是否正確? 有沒有辦法丟棄以前的數據報並重新開始?

UdpClient.Receive方法上的參數remoteEP不是用於指定從哪個遠程端點接收數據,而是指定哪個遠程端點發送數據。 您不能有選擇地僅從特定端點接收。

相反,您必須從每個人那里接收所有內容,並丟棄不是從您想要的遠程端點發送的包。 你可以這樣做:

byte[] receivedData = null;
var attempts = 0;

while (attempts < 10)
{
    var recvEp = new IPEndPoint(IPAddress.Any, 0);
    readData = myUDP.Receive(ref recvEp);
  
    if (recvEp.Address == selectedIPAddress)
    {
       // We received data from the correct remote source
       receivedData = readData;
       break;
    }

    attempts++;
}

此代碼將從任何地方接收數據,如果在 10 次嘗試內沒有從正確的端點接收數據,它將停止。 導致receivedData為空。

您可能希望將代碼轉換為等待一定時間而不是一定數量的嘗試,以增加實際接收某些內容的機會。 這可以像這樣完成:

var start = DateTime.Now;
byte[] receivedData = null;

while((DateTime.Now - start).TotalSeconds < 10)
{
    var recvEp = new IPEndPoint(IPAddress.Any, 0);
    readData = myUDP.Receive(ref recvEp);
  
    if (recvEp.Address == selectedIPAddress)
    {
       // We received data from the correct remote source
       receivedData = readData;
       break;
    }
}

此代碼將嘗試 10 秒,如果未收到任何內容,則在 10 秒后停止。 這不是完全干凈的代碼,例如,如果您願意,您可以使整個事情異步。


注意:這兩個代碼片段可能會導致無限循環,因為只要沒有任何傳入數據, myUDP.Receive(ref recvEp)就會阻塞。 因此,如果您的所有遠程端點決定同時停止發送數據,則接收調用將永遠不會返回

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM