1

我下载了 WinDDK 并使用 ndisprot 5x 从我的用户应用程序广播原始以太网数据包,将目标 MAC 全部指定为 0xff,在大型且重复的数据集上,它似乎不是很有效率。

目前最有效的是环回 - 将目标和源 MAC 指定为我自己的我获得所需的速度,但数据包永远不会离开我的网卡。

也许我错过了一些 ndis 驱动程序选项并等待使用此示例 MS 驱动程序完成广播?我想要的只是将数据包广播到网络,我并不真正关心交付状态并希望尽快摆脱它。

只有 2 分的系统在这里有帮助吗?我不确定是什么导致了延迟。

4

1 回答 1

1

在内核模式下不可能消除发送完成路径。原因是网卡忙于从内存中读取字节,直到它最终发出发送完成。如果您在重新使用数据包之前没有等待发送完成,那么网卡将没有机会读取完整的数据包。您最终会发送损坏的数据。

但是,您是对的,当使用库存 NDISPROT 样本发送大量数据时效率非常低。问题是 NDISPROT 的用户模式示例应用程序将数据同步写入内核模式。这意味着您的线程开始写入(发送数据包),然后阻塞直到写入(发送数据包)完成。(该示例效率低下,因为 NDISPROT 示例的目的是说明如何在内核模式下与 NDIS 进行互操作,而不是说明用户与内核通信的复杂技术。)

您可以通过使用多种技术中的一种同时发布多条数据来大大加快速度:

  1. 使用多线程。做你现在正在做的同样的事情,除了在多个线程上并行执行。这很容易设置,但扩展性不是很好(要扩展至 10 倍流量,您需要 10 倍线程,然后您开始在缓存问题上受到伤害)。另外,如果你的数据集必须按顺序发送,你需要一堆复杂的同步来确保线程按顺序发出请求。

  2. 对 WriteFile 和 OVERLAPPED 数据结构使用异步调用。这需要您对用户模式应用程序进行一些改造。(幸运的是,您不需要接触内核驱动程序,因为它已经支持这一点)。使用 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 中。相反,如果您对内核模式使用异步写入,您将得到以下结果:

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,请从本文档开始。(哎呀,看起来他们的图表从我很棒的 ASCII-art 旋转了 90°...)。

于 2011-07-09T02:04:58.653 回答