什么可能导致 UDP 数据包计时不一致?
Posted
技术标签:
【中文标题】什么可能导致 UDP 数据包计时不一致?【英文标题】:What could be causing UDP Packet timings to be inconsistent? 【发布时间】:2022-01-05 12:10:55 【问题描述】:我一直在研究一个读取鼠标输入的项目,然后通过 UDP 将其发送到另一台计算机,然后重新创建鼠标输入。我在 UDP 数据包计时方面遇到了奇怪的问题,仅在我的一台计算机上,似乎 UDP 数据包可能被组合在一起?我已经设置了一些简单的代码,它每 10 毫秒发送一个大约 12 个字节的 udp 数据包
while(true)
Packet p = new Packet(Packet.Type.MOUSE_MOVE, id++, (float)50, (float)50);
Send(p);
System.Threading.Thread.Sleep(10);
但是,接收这些数据包的服务器并没有像我预期的那样每 10 毫秒接收一个数据包。
相反,测量“自上次数据包以来的时间”会显示以下时间:
[1440] [6.0834ms] MOUSE_MOVE: 50, 50
[1441] [8.4989ms] MOUSE_MOVE: 50, 50
[1442] [9.7771ms] MOUSE_MOVE: 50, 50
[1443] [59.8888ms] MOUSE_MOVE: 50, 50
[1444] [0ms] MOUSE_MOVE: 50, 50
[1445] [0.4995ms] MOUSE_MOVE: 50, 50
[1446] [0.4985ms] MOUSE_MOVE: 50, 50
[1447] [0ms] MOUSE_MOVE: 50, 50
[1448] [0ms] MOUSE_MOVE: 50, 50
[1449] [6.0016ms] MOUSE_MOVE: 50, 50
[1450] [6.001ms] MOUSE_MOVE: 50, 50
[1451] [10.0007ms] MOUSE_MOVE: 50, 50
[1452] [64.4198ms] MOUSE_MOVE: 50, 50
[1453] [0ms] MOUSE_MOVE: 50, 50
[1454] [0.5021ms] MOUSE_MOVE: 50, 50
[1455] [0ms] MOUSE_MOVE: 50, 50
[1456] [0.5017ms] MOUSE_MOVE: 50, 50
[1457] [0ms] MOUSE_MOVE: 50, 50
[1458] [5.4997ms] MOUSE_MOVE: 50, 50
[1459] [7.4957ms] MOUSE_MOVE: 50, 50
[1460] [10.5004ms] MOUSE_MOVE: 50, 50
[1461] [66.7724ms] MOUSE_MOVE: 50, 50
[1462] [0ms] MOUSE_MOVE: 50, 50
[1463] [1.5007ms] MOUSE_MOVE: 50, 50
[1464] [0ms] MOUSE_MOVE: 50, 50
[1465] [0ms] MOUSE_MOVE: 50, 50
显然,我的代码之外一定有某些东西,或者 UdpClient 中的某些设置正在改变幕后的时间,否则我看不出我的服务器如何可能以
另一件值得注意的事情是,有时“数据包之间的时间”测量值会达到 60 毫秒左右。我测量了这种情况发生的频率,它似乎每 100 毫秒就会出现一次峰值(给或需要 1 或 2 毫秒)
基于此,我认为必须在发送数据包之前将它们缓冲或组合在一起,可能会在 100 毫秒内收集所有数据包,然后一次性发送所有数据包。
还有一件事,我只在一台测试计算机上体验过这种类型的分组,这让我相信它可能是操作系统或驱动程序问题。该问题仅发生在 Microsoft Surface Go 上,因此它可能与它是一款动力不足的设备有关。任何帮助将不胜感激。
客户端是这样创建的:
var ip = new IPAddress(new byte[] 192, 168, 178, 63 );
endPoint = new IPEndPoint(ip, Common.Constants.SERVER_PORT);
client = new UdpClient();
client.Connect(endPoint);
和发送功能:
private void Send(Packet p)
var data = p.ToByteArray();
client.Send(data, data.Length);
接收线程:
private static void ServerThread()
while (running)
var clientEndPoint = new IPEndPoint(IPAddress.Any, 0);
var clientData = server.Receive(ref clientEndPoint);
if (clientData.Length > 0)
Packet p = new Packet(clientData);
var time = DateTime.Now - last;
Console.WriteLine($"[p.id] [time.TotalMillisecondsms] p.type: p.x, p.y");
last = DateTime.Now;
if (p.type == Packet.Type.MOUSE_MOVE)
SetCursorPos((int)p.x, (int)p.y);
【问题讨论】:
发生这种情况的原因有很多。无论您做什么,UDP 数据包都可以并且将会被打包在一起。但是有一些套接字选项可以减轻一些违规行为并更快地发送。但是您需要显示显示套接字是如何创建的代码。最好也显示Send
的代码。还有你的recv
代码。
另外,仅仅因为您调用 Sleep(10)
并不意味着您将在 10 毫秒后准确地醒来。无论如何,您必须准备好在发送端和接收端处理代码中的抖动——尤其是当您每秒发送 100 个数据包时。另一个问题:除了最后一个数据包,你为什么还要关心鼠标的移动?
@selbie 我添加了您要求的额外信息,但我假设调用 Sleep(10)
至少会休眠超过 1 毫秒。至于为什么我需要对每个数据包进行一致的鼠标移动,是因为该项目是专门针对数字绘图/雕刻的远程工作,因此笔画的形状至关重要。您是否有任何您提到的套接字选项的示例?
【参考方案1】:
我认为问题出在这一行:
System.Threading.Thread.Sleep(10);
系统的计时器不是很准确。 您可以找到更准确的计时器来执行此操作。
【讨论】:
【参考方案2】:我相信我可能找到了解决方案,通过禁用“Microsoft Virtual WiFi Adapter”,数据包时序似乎变得更加一致。
在提升的命令提示符下:
netsh wlan stop hostednetwork
netsh wlan set hostednetwork mode=disallow
【讨论】:
以上是关于什么可能导致 UDP 数据包计时不一致?的主要内容,如果未能解决你的问题,请参考以下文章