2010-02-17 14 views
28

Zastanawiam się, czy mogę ustawić wartość limitu czasu dla metody odbioru UdpClient.Czy mogę ustawić limit czasu dla UdpClient w C#?

Chcę użyć trybu blokowego, ale ponieważ czasami udp straci pakiet, mój program udpClient.receive będzie zawieszony na zawsze.

Jakieś dobre pomysły, jak sobie z tym poradzić?

Odpowiedz

21

To, o czym Filip mówi, jest zagnieżdżone w gnieździe, które zawiera UdpClient (UdpClient.Client.ReceiveTimeout).

Można również użyć metody async to zrobić, ale ręcznie zablokować wykonanie:

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

Dzięki za odpowiedź. – Jack

+0

To było dawno temu! Teraz wygląda dobrze. WaitOne zwraca również wynik, którego można użyć do ustalenia, czy upłynął limit czasu. – weston

2

Istnieje właściwość ReceiveTimeout, z której można korzystać.

53

Jest SendTimeout i właściwość ReceiveTimeout które można wykorzystać w Socket z UdpClient.

Oto przykład 5 drugim timeout:

var udpClient = new UdpClient(); 

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

... 
+0

Działa to tylko w przypadku synchronicznego wysyłania/odbierania. W przypadku wywołań ansynchronicznych można użyć polecenia 'Task.Delay', aby utworzyć własny limit czasu, np. 'Task.WhenAny (udpClient.ReceiveAsync(), Task.Delay (5000))'; –

+0

No oczywiście! Jak przegapiłem to proste rozwiązanie! Dzięki za twój komentarz AJ! –

3

Faktycznie, wydaje się, że UdpClient jest uszkodzony, jeśli chodzi o limity czasu. Próbowałem napisać serwer z wątkiem zawierającym tylko Odbiór, który dostał dane i dodał je do kolejki. Robiłem tego rodzaju rzeczy przez lata z TCP. Oczekuje się, że pętla blokuje się w odbiorze, dopóki nie pojawi się komunikat od requestera. Jednak pomimo ustawienia limitu czasu na nieskończoność:

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

gniazdo kończy się po około 3 minutach.

Jedynym sposobem obejścia tego problemu było złapanie wyjątku limitu czasu i kontynuowanie pętli. To ukrywa błąd Microsoftu, ale nie odpowiada na podstawowe pytanie, dlaczego tak się dzieje.

+1

Przypuszczam, że istnieje wewnętrzny limit czasu wynoszący 200000 ms? –

1

można zrobić tak:

udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000); 
Powiązane problemy