我可以在 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】:

您可以在UdpClientSocket 中使用SendTimeoutReceiveTimeout 属性。

以下是 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 设置超时吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用 UdpClient C# 发送对象

C#:UdpClient 很快调用 close() 时不发送数据

如何使用 C# UdpClient 发送大数据?

在 angularjs 中为 promise 设置超时处理程序

C# UDPClient 接受任何 IP 地址

C#里使用UdpClient和线程来创建UDP网络通讯