Могу ли я установить тайм-аут для UdpClient в C#?
Мне интересно, могу ли я установить значение тайм-аута для метода UdpClient receive.
Я хочу использовать режим блока, но потому, что иногда udp потеряет пакет, моя программа udpClient.прием будет висеть там вечно.
есть хорошие идеи, как я могу это сделать?
5 ответов
то, что Филип имеет в виду, вложено в сокет, который 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
}
есть SendTimeout
и ReceiveTimeout
свойство, которое можно использовать в Socket
на UdpClient
.
вот пример 5-секундного таймаута:
var udpClient = new UdpClient();
udpClient.Client.SendTimeout = 5000;
udpClient.Client.ReceiveTimeout = 5000;
...
на самом деле, оказывается, что UdpClient
нарушается, когда дело доходит до тайм-ауты. Я попытался написать сервер с потоком, содержащим только Receive, который получил данные и добавил их в очередь. Я делал такие вещи в течение многих лет с TCP. Ожидание заключается в том, что цикл блокируется при получении, пока сообщение не поступит от запрашивающего. Однако, несмотря на установку тайм-аута на бесконечность:
_server.Client.ReceiveTimeout = 0; //block waiting for connections
_server.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 0);
гнездо через 3 минуты.
только обходной путь, который я нашел, состоял в том, чтобы поймать исключение тайм-аута и продолжить цикл. Это скрывает ошибку Microsoft, но не может ответить на фундаментальный вопрос, почему это происходит.
можно сделать так:
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000);