我下载了WinDDK并使用ndisprot 5x从我的用户应用程序广播原始以太网数据包,指定目标MAC全部为0xff,在大型和重复数据集上,它似乎效率不高。
目前效果很好的是环回 - 指定目标和源MAC作为我自己的我需要的速度,但数据包永远不会离开我的网卡。
也许我错过了一些ndis驱动程序选项并等待使用此示例MS驱动程序完成广播?我想要的只是要广播到网络的数据包,我并不关心交付状态,并希望尽快摆脱它。
只有2分的系统会帮助吗?我不确定是什么导致了延迟。
答案 0 :(得分:1)
在内核模式下无法消除发送完成路径。原因是网卡正在忙于从内存中读取字节,直到它最终发出发送完成。如果您在重新使用数据包之前没有等待发送完成,那么网卡就没有机会读取完整的数据包。你最终会发送损坏的数据。
但是,使用NDISPROT库存样本发送大量数据时,效率很低是正确的。问题是NDISPROT的usermode示例应用程序将数据写入kernelmode 同步。这意味着您的线程开始写入(发送数据包),然后阻塞直到写入(发送数据包)完成。 (样本效率低下,因为NDISPROT示例的目的是说明如何在内核模式中与NDIS进行互操作,而不是说明用户内核通信的复杂技术。)
通过使用多种技术之一同时发布多个数据,您可以大大提高速度:
使用多线程。做你现在正在做的事情,除了并行地在多个线程上做。这很容易设置,但它不能很好地扩展(扩展到10倍流量,你需要10个线程,然后你开始受到缓存问题的伤害)。另外,如果必须按顺序发送数据集,则需要进行大量复杂的同步,以确保线程按顺序发出请求。
使用WriteFile和OVERLAPPED数据结构的异步调用。这需要您在usermode应用程序上进行一些重组。 (幸运的是,你不需要触摸内核驱动程序,因为那已经支持了这一点)。使用OVERLAPPED写入,您可以从单个线程发出多个同时写入,然后在任何(或全部)完成时收到通知。如果您对重叠设计足够小心,您应该能够轻松填充100Mbps网络链接。
更明确地说,这就是你今天所拥有的:
Your app NDISPROT driver Network card The network
---------------------------------------------------------------------------------
WriteFile
. \-------> NdisProtWrite
. \-------> NdisSendPackets
. |
. (copy packet payload
. from system RAM to
. network card's buffer)
. |
. |---------------> Start sending
. NdisProtSendComplete <---------| .
WriteFile <----/ | .
returns |<--------------- Finish sending
如您所见,您的用户模式应用程序在网卡将数据包有效负载从RAM复制到NIC硬件的整个时间内都停留在WriteFile中。相反,如果你使用异步写入kernelmode,你最终会得到这个:
Your app NDISPROT driver Network card The network
---------------------------------------------------------------------------------
WriteFile
. \-------> NdisProtWrite
. | \-------> NdisSendPackets
WriteFile <------/ |
returns (copy packet payload
from system RAM to
network card's buffer)
|
|---------------> Start sending
NdisProtSendComplete <---------| .
Async write <--/ | .
completes |<--------------- Finish sending
在此设置中,WriteFile返回的速度更快,因此当NIC仍在读取第一个数据包时,您有机会排队另一个数据包(或10)。您可以使用任何常用的OVERLAPPED技术来确定写入(发送数据包)何时完成,并且您可以重用数据缓冲区。
要开始使用异步I / O,请从this documentation开始。 (糟糕,看起来他们的图表与我真棒的ASCII艺术相比旋转了90°......)。