如何在C++中以指定速率发送UDP数据包在 Windows 上?
我正在编写一个实现 RFC 2544 网络测试的程序。作为测试的一部分,我必须以指定的速率发送 UDP 数据包。
例如,我应该以 1Gb/s 的速度发送 64 字节数据包。这意味着我应该每 0.5 微秒发送一次 UDP 数据包。伪代码看起来像“以指定的速率发送 UDP 数据包rate":
while (true) {
some_sleep (0.5);
Send_UDP();
}
但恐怕 Windows 和 Linux 中都没有 some_sleep()
函数可以给我 0.5 微秒的分辨率。
是否可以在 C++ 中完成此任务,如果可以,正确的方法是什么?
I'm writing a program that implements the RFC 2544 network test. As the part of the test, I must send UDP packets at a specified rate.
For example, I should send 64 byte packets at 1Gb/s. That means that I should send UDP packet every 0.5 microseconds. Pseudocode can look like "Sending UDP packets at a specified rate":
while (true) {
some_sleep (0.5);
Send_UDP();
}
But I'm afraid there is no some_sleep()
function in Windows, and Linux too, that can give me 0.5 microseconds resolution.
Is it possible to do this task in C++, and if yes, what is the right way to do it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
两种方法:
使用高分辨率计时器(例如 Windows QueryPerformanceCounter)通过忙循环实现您自己的睡眠
允许如果速率略有变化,当您足够提前计算速率时,插入 Sleep(1)。使用 timeBeginPeriod 获得 1ms 分辨率。
对于这两种方法,您不能依赖精确的睡眠。您需要保留总数计数器并在领先/落后时调整睡眠时间。
Two approaches:
Implement your own sleep by busy-looping using a high-resolution timer such as windows QueryPerformanceCounter
Allow slight variations in rate, insert Sleep(1) when you're enough ahead of the calculated rate. Use timeBeginPeriod to get 1ms resolution.
For both approaches, you can't rely on the sleeps being exact. You will need to keep totals counters and adjust the sleep period as you get ahead/behind.
这可能会有帮助,但我怀疑它是否可以直接移植到 Windows 以外的任何平台。 为 Windows 实现持续更新的高分辨率时间提供程序,作者:Johan Nilsson 。
但是,请记住,对于这么小的数据包,IP 和 UDP 开销将占实际在线数据的很大一部分。这可能是您想要的,也可能不是。对 RFC 2544 的快速扫描表明允许更大的数据包;你最好还是走那条路。在每次
Send_UDP()
调用之间始终延迟 0.5 微秒,充其量也是很困难的。This might be helpful, but I doubt it's directly portable to anything but Windows. Implement a Continuously Updating, High-Resolution Time Provider for Windows by Johan Nilsson.
However, do keep in mind that for packets that small, the IP and UDP overhead is going to account for a large fraction of the actual on-the-wire data. This may be what you intended, or not. A very quick scan of RFC 2544 suggests that much larger packets are allowed; you may be better off going that route instead. Consistently delaying for as little as 0.5 microseconds between each
Send_UDP()
call is going to be difficult at best.要以线速传输 64 字节以太网帧,您实际上希望每 672 ns 发送一次。我认为做到这一点的唯一方法就是对硬件非常友好。您将遇到 PCI 总线等的带宽限制。发送一个数据包的系统调用将花费比 672 ns 长得多的时间。睡眠功能是您最不用担心的。
To transmit 64-byte Ethernet frames at line rate, you actually want to send every 672 ns. I think the only way to do that is to get really friendly with the hardware. You'll be running up against bandwidth limitations with the PCI bus, etc. The system calls to send one packet will take significantly longer than 672 ns. A sleep function is the least of your worries.
您猜想您应该能够使用
Boost Asio
的计时器功能来做到这一点。我自己还没有尝试过,但我猜deadline_timer
会需要boost::posix_time::nanosec
以及boost::posix_time::第二
查看示例此处< /a>
You guess you should be able to do it with
Boost Asio
s timer function. I haven't tried it myself, but I guess thatdeadline_timer
would take aboost::posix_time::nanosec
as well as theboost::posix_time::second
Check out an example here
这是
nanosleep< 的本机 Windows 实现< /代码>。如果 GPL 可以接受,您可以重用该代码,否则您将不得不重新实现。
Here's a native Windows implementation of
nanosleep
. If GPL is acceptable you can reuse the code, else you'll have to reimplement.