【发布时间】:2023-03-28 14:33:01
【问题描述】:
我一直在研究一个读取鼠标输入的项目,然后通过 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.TotalMilliseconds}ms] {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 毫秒。至于为什么我需要对每个数据包进行一致的鼠标移动,是因为该项目是专门针对数字绘图/雕刻的远程工作,因此笔画的形状至关重要。您是否有任何您提到的套接字选项的示例?
标签: c# windows sockets networking udp