我可以在 C# 中为 UdpClient 设置超时吗?
Posted
技术标签:
【中文标题】我可以在 C# 中为 UdpClient 设置超时吗?【英文标题】:Can I set the timeout for UdpClient in C#? 【发布时间】:2011-01-17 21:29:17 【问题描述】:我想知道是否可以为 UdpClient 接收方法设置超时值。
我想使用阻塞模式,但是因为有时udp会丢包,我的程序udpClient.receive会永远挂在那里。
我有什么好主意吗?
【问题讨论】:
【参考方案1】:您可以在UdpClient
的Socket
中使用SendTimeout
和ReceiveTimeout
属性。
以下是 5 秒超时的示例:
var udpClient = new UdpClient();
udpClient.Client.SendTimeout = 5000;
udpClient.Client.ReceiveTimeout = 5000;
...
【讨论】:
这仅在您进行同步发送/接收时有效。对于异步调用,您可以使用Task.Delay
创建自己的超时,例如Task.WhenAny(udpClient.ReceiveAsync(), Task.Delay(5000))
;
当然好!我怎么会错过这个简单的解决方案!感谢您的评论 AJ!
@AJRichardson 好吧,我认为这不是一个好方法,因为当 timer -ask 完成时,该过程将恢复但 udpClient.ReceiveAsync() 仍将等待.. . 我建议可能是这样的:Task.WaitAny(new[] udpClient.ReceiveAsync() , waitTimeOutInMs);
@IvandroJao 你是对的,虽然我不知道你的代码能解决这个问题。听起来你应该在超时情况下关闭套接字:见***.com/a/12642359/1299394【参考方案2】:
Filip 所指的内容嵌套在 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
【讨论】:
这是很久以前的事了!现在看起来没问题。 WaitOne 还会返回一个结果,您可以使用它来确定它是否超时。【参考方案3】:实际上,UdpClient
似乎在超时时被破坏了。我试图用一个线程编写一个服务器,该线程只包含一个接收数据并将其添加到队列中。多年来,我一直在使用 TCP 做这类事情。期望是循环在接收时阻塞,直到消息来自请求者。但是,尽管将超时设置为无穷大:
_server.Client.ReceiveTimeout = 0; //block waiting for connections
_server.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 0);
套接字在大约 3 分钟后超时。
我发现的唯一解决方法是捕获超时异常并继续循环。这隐藏了 Microsoft 错误,但未能回答为什么会发生这种情况的根本问题。
【讨论】:
我猜有 200000 毫秒左右的内部超时?【参考方案4】:你可以这样做:
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000);
【讨论】:
【参考方案5】:您可以使用 ReceiveTimeout 属性。
【讨论】:
ReceiveTimeout 仅用于同步调用(即:接收方法)以上是关于我可以在 C# 中为 UdpClient 设置超时吗?的主要内容,如果未能解决你的问题,请参考以下文章
C#:UdpClient 很快调用 close() 时不发送数据