我想知道是否可以为UdpClient的接收方法设置超时值。
我想使用阻塞模式,但因为有时候udp会丢失数据包,我的程序中udpClient.receive方法会一直挂在那里。
你有什么好的方法来解决这个问题吗?
在UdpClient
的Socket
中有一个SendTimeout
和ReceiveTimeout
属性可供使用。
以下是5秒超时的示例:
var udpClient = new UdpClient();
udpClient.Client.SendTimeout = 5000;
udpClient.Client.ReceiveTimeout = 5000;
...
菲利普所指的是嵌套在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
}
实际上,看起来 UdpClient
在超时方面存在问题。我试图编写一个只包含 Receive
方法的线程服务器来获取数据并将其添加到队列中。多年来,我一直用 TCP 做这样的事情。期望的是循环在接收到请求方发来的消息前一直阻塞在接收处。然而,即使将超时设置为无限大:
_server.Client.ReceiveTimeout = 0; //block waiting for connections
_server.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 0);
套接字在大约3分钟后超时。
我找到的唯一解决方法是捕获超时异常并继续循环。这隐藏了微软的错误,但未能回答为什么会发生这种情况的根本问题。
你可以这样操作:
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000);
您可以使用ReceiveTimeout属性。
Task.Delay
创建自己的超时,例如Task.WhenAny(udpClient.ReceiveAsync(), Task.Delay(5000))
; - AJ Richardson