等待 UDP 接收时我的计时器缓冲区会溢出吗?

Posted

技术标签:

【中文标题】等待 UDP 接收时我的计时器缓冲区会溢出吗?【英文标题】:Will my timer buffer overflow while waiting for UDP receive? 【发布时间】:2016-02-17 01:46:37 【问题描述】:

我正在编写一个软件,它将接收来自 UDP 数据包的数据,然后将其写入文件。这是我作为控制台应用程序编写的示例代码,用于测试 UdpClient 类。

while(!done)

Console.WriteLine("Receiving");
byte[] bytes = listener.Receive(ref groupEP);
Console.WriteLine("Received");

我发现如果没有收到 UDP 数据包,while 循环将在 Receive(ref groupEP) 函数处暂停。只有在收到 UDP 数据包时,才会继续打印“已接收”。

但是对于实际程序(WPF),为了节省资源,我使用了计时器。目前更新接口和文件工作正常,但我一直想知道如果每 100 毫秒调用一次计时器会发生什么,而 UDP 数据包仅每 1 秒接收一次(假设我不知道什么时候会收到 UDP所以我选择100ms)。 这不会导致每 1 秒有 9 个冗余计时器调用,这会导致溢出吗?目前该应用程序在这个场景中运行良好,但我想了解为什么以及是否有任何可能的后果。

【问题讨论】:

【参考方案1】:

这个问题“太宽泛”了。你提出了很多不同的问题。也就是说,尽量保持简短……

计时器的行为取决于您实际使用的哪个计时器。如果您正在使用DispatcherTimer 并从计时器事件处理程序调用Receive(),那么您将不会获得多余的计时器事件,因为您将阻塞 UI 线程。这实际上一点都不好,但至少不会导致获得太多计时器事件。 如果您使用的是其他类型的计时器,那么是的……在完成前一个操作之前发出新的Receive() 操作将导致未完成的Receive() 操作数量不断增加。您可以通过将套接字置于非阻塞模式来解决此问题,但这会打开一个全新的蠕虫罐。所以……

事实上,您根本不应该使用阻塞 Receive() 方法,也不应该使用任何与 I/O 相关的计时器。您应该使用 ReceiveFrom() 的异步版本,例如BeginReceiveFrom(),您可以将其包装在 Task.Factory.FromAsync() 中,以便您可以使用 await 而不是处理回调。 (您应该使用ReceiveFrom(),这样您才能真正获取您收到的数据报的远程端点信息)。

使用此技术时,您将循环使用await(如果使用FromAsync()),或者在处理完成的操作时再次调用BeginReceiveFrom()(如果您使用旧式回调机制)。这样,您一次只能激活一个接收操作,而不会阻塞任何线程,因此无需使用计时器或其他机制来轮询套接字。

【讨论】:

如果我一直调用ReceiveFrom()会不会一样,只是我一直通过我的定时器调用函数生成异步线程? 对不起,如果我的回答不够清楚。我将对其进行编辑以尝试改进它。每个数据报只能调用一次BeginReceiveFrom()。在第一次调用之后,你什么都不做,直到它完成并且你已经处理了数据报。然后你再次调用它。在这种方法中,您根本不会使用计时器。

以上是关于等待 UDP 接收时我的计时器缓冲区会溢出吗?的主要内容,如果未能解决你的问题,请参考以下文章

有睡眠/等待吗?

浅谈TCP/IP四种计时器慢启动拥塞避免快速重传快速恢复

浅谈TCP/IP四种计时器慢启动拥塞避免快速重传快速恢复

什么可能导致 UDP 数据包计时不一致?

如何使用计时器等待?

我可以使用 Excel for Mac 将代码计时到毫秒吗