Могу ли я установить тайм-аут для UdpClient в C #? - PullRequest
33 голосов
/ 17 февраля 2010

Мне интересно, могу ли я установить значение времени ожидания для метода приема UdpClient.

Я хочу использовать блочный режим, но поскольку иногда udp теряет пакет, моя программа udpClient.receive будет зависать там вечно.

есть хорошие идеи, как мне справиться с этим?

Ответы [ 5 ]

56 голосов
/ 16 апреля 2011

Существует свойство SendTimeout и ReceiveTimeout, которое можно использовать в Socket из UdpClient.

Вот пример 5-секундного тайм-аута:

var udpClient = new UdpClient();

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

...
25 голосов
/ 17 февраля 2010

То, на что ссылается Филипп, вложено в сокет, содержащий UdpClient (UdpClient.Client.ReceiveTimeout).

Для этого вы также можете использовать асинхронные методы, но блокировать выполнение вручную:

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
}
3 голосов
/ 01 июня 2012

На самом деле, кажется, что UdpClient не работает, когда дело доходит до тайм-аута. Я попытался написать сервер с потоком, содержащим только Receive, который получил данные и добавил их в очередь. Я делал подобные вещи годами с помощью TCP. Ожидается, что цикл блокируется на приеме до тех пор, пока не поступит сообщение от запрашивающей стороны. Однако, несмотря на установку времени ожидания на бесконечность:

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

истечение времени ожидания через 3 минуты.

Единственный обходной путь, который я нашел, - перехватить исключение тайм-аута и продолжить цикл. Это скрывает ошибку Microsoft, но не может ответить на фундаментальный вопрос, почему это происходит.

2 голосов
/ 17 февраля 2010

Существует свойство ReceiveTimeout, которое вы можете использовать.

1 голос
/ 29 августа 2017

вы можете сделать так:

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