2010-02-17 4 views
28

Ich frage mich, ob ich einen Timeout-Wert für UdpClient-Empfangsmethode festlegen kann.Kann ich die Zeitüberschreitung für UdpClient in C# festlegen?

Ich möchte den Block-Modus verwenden, aber weil manchmal udp Paket verloren geht, wird mein Programm udpClient.receive dort für immer hängen.

irgendwelche guten Ideen, wie ich das schaffen kann?

Antwort

21

Worauf Filip verweist, ist innerhalb des Sockets verschachtelt, das UdpClient enthält (UdpClient.Client.ReceiveTimeout).

Sie können auch die Asynchron-Methoden verwenden, um dies zu tun, aber manuell Ausführung blockieren:

var timeToWait = TimeSpan.FromSeconds(10); 

var udpClient = new UdpClient(portNumber); 
var asyncResult = udpClient.BeginReceive(null, null); 
asyncResult.AsyncWaitHandle.WaitOne(timeToWait); 
if (asyncResult.IsCompleted) 
{ 
    try 
    { 
     IPEndPoint remoteEP = null; 
     byte[] receivedData = udpClient.EndReceive(asyncResult, ref remoteEP); 
     // EndReceive worked and we have received data and remote endpoint 
    } 
    catch (Exception ex) 
    { 
     // EndReceive failed and we ended up here 
    } 
} 
else 
{ 
    // The operation wasn't completed before the timeout and we're off the hook 
} 
+1

Danke für die Antwort. – Jack

+0

Das war vor langer Zeit! Das sieht jetzt gut aus. WaitOne gibt auch ein Ergebnis zurück, mit dem Sie feststellen können, ob das Zeitlimit überschritten wurde. – weston

2

Es gibt eine ReceiveTimeout-Eigenschaft, die Sie verwenden können.

53

Es gibt eine SendTimeout und eine ReceiveTimeout Eigenschaft, die Sie in den Socket der UdpClient verwenden können. Hier

ist ein Beispiel für eine 5 Sekunden timeout:

var udpClient = new UdpClient(); 

udpClient.Client.SendTimeout = 5000; 
udpClient.Client.ReceiveTimeout = 5000; 

... 
+0

Dies funktioniert nur, wenn Sie ein synchrones Senden/Empfangen durchführen. Für anonyme Aufrufe können Sie 'Task.Delay' verwenden, um ein eigenes Zeitlimit zu erstellen, z. 'Task.WhenAny (udpClient.ReceiveAsync(), Task.Delay (5000))'; –

+0

Gut natürlich! Wie habe ich diese einfache Lösung vermisst? Danke für deinen Kommentar AJ! –

3

Tatsächlich scheint es, dass UdpClient gebrochen ist, wenn es um Timeouts kommt. Ich habe versucht, einen Server mit einem Thread zu schreiben, der nur einen Receive enthält, der die Daten erhalten und zu einer Warteschlange hinzugefügt hat. Ich habe diese Art von Dingen seit Jahren mit TCP gemacht. Die Erwartung ist, dass die Schleife beim Empfang blockiert, bis eine Nachricht von einem Anforderer eintrifft. Doch trotz Einstellung des Timeout auf unendlich:

_server.Client.ReceiveTimeout = 0; //block waiting for connections 
_server.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 0); 

die Buchse Timeout nach ca. 3 Minuten.

Die einzige Problemumgehung, die ich gefunden habe, war, die Timeout-Ausnahme zu fangen und die Schleife fortzusetzen. Dies verbirgt den Microsoft-Fehler, aber versäumt, die grundlegende Frage zu beantworten, warum dies geschieht.

+1

Ich denke, es gibt eine interne Zeitüberschreitung von 200000 ms oder so? –

1

Sie können wie folgt tun:

udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000);