【问题标题】:NdisProt takes a long time to write Ethernet packetsNdisProt 写入以太网数据包耗时较长
【发布时间】:2014-11-28 04:27:04
【问题描述】:

我正在用 C# 开发一个需要网络访问的虚拟化应用程序。我正在使用 ndisprot 示例驱动程序来读取和写入以太网第 2 层数据包。我一切正常,除了 WriteFile 操作需要大量时间。通常在 300-800 毫秒之间,但有时需要几秒钟才能完成写入。

这是我的 C# 函数,它将以太网数据包写入驱动程序。我正在使用秒表来测量需要多长时间。

private Stopwatch sw = new Stopwatch();

/// <summary>
/// Writes a layer-2 Ethernet packet to the adapter
/// </summary>
/// <param name="packet">The packet data</param>
/// <returns>true if the write was successful</returns>
public bool WriteEnetPacket(byte[] packet)
{
   int bytesSent = 0;
   bool packetSent = false;

   // Copy the packet data to raw buffer
   IntPtr packetPtr = Marshal.AllocHGlobal(packet.Length);
   Marshal.Copy(packet, 0, packetPtr, packet.Length);

   sw.Restart();
   packetSent = WriteFile(this.handle, 
      packetPtr, 
      packet.Length,
      out bytesSent, 
      0);

   sw.Stop();
   Console.WriteLine("WriteFile completed in {0}ms", sw.Elapsed.Milliseconds);

   // Free the memory
   Marshal.FreeHGlobal(packetPtr);

   // check to see if packet was sent
   if (!packetSent)
   {
      var err = UnsafeMethods.GetLastError();
      var errStr = UnsafeMethods.GetLastErrorString();

      Console.WriteLine("ERROR: Packet not sent: 0 bytes written.");
      Console.WriteLine("Reason: " + errStr);
      return false;
   }

   // otherwise the packet was sent
   Console.WriteLine("Packet sent: " + bytesSent.ToString() + "bytes written");
   return true;
}

当我运行我的应用程序时,我的输出如下所示。我正在使用有线连接。

Packet sent: 42bytes written
WriteFile completed in 160ms
Packet sent: 42bytes written
WriteFile completed in 458ms
Packet sent: 74bytes written
WriteFile completed in 364ms
Packet sent: 74bytes written
WriteFile completed in 51ms
Packet sent: 86bytes written
WriteFile completed in 221ms
Packet sent: 74bytes written
WriteFile completed in 271ms
Packet sent: 74bytes written
WriteFile completed in 1ms
Packet sent: 74bytes written
WriteFile completed in 292ms

如果我 ping 我的应用程序,响应时间几乎与 WriteFile 完成所需的时间完全匹配,因此我知道挂断在驱动程序的某个地方。我可以在示例驱动程序中做些什么来加快速度吗?我做错了什么?

编辑:今天我尝试使用我的 USB 以太网适配器而不是内置适配器,但性能更差!完成写作需要 15-30 秒。这是最奇怪的,因为阅读几乎是瞬时的。

Edit2:我的驱动程序有两个线程——一个读线程和一个写线程。似乎如果我禁用我的阅读器线程,写入会立即完成。为什么读取文件会影响写入?

【问题讨论】:

    标签: networking driver ethernet wdk ndis


    【解决方案1】:

    为什么读取会减慢写入速度?

    您的用户模式代码可能在同步模式下打开了句柄。在同步模式下,每个句柄一次只能服务 1 个调用,即使 2 个不同的线程在同一个句柄上工作。 More here.

    解决方法是:

    • 打开 N 个句柄以获得 N 个同时操作;或
    • OVERLAPPED模式下打开句柄。如果你有使用 C# 编码的奢侈,你会使用FileOptions.Asynchronous

    为什么发送一个数据包需要 200 毫秒?

    NDISPROT 示例设计得非常简单。在 NIC 完成数据包之前,它会一直写入块。这就是为什么写入需要数百毫秒。此外,由于句柄是在同步模式下打开的,这意味着在第一个数据包完成之前,您无法发送第二个数据包。

    对于任何严重的吞吐量来说,这方式太慢了;你需要在某处引入异步。在此处查看更多讨论:Raw ethernet broadcasting

    【讨论】:

    • 谢谢,看来你是对的。我发现我可以使用 WinpCap 驱动程序来完成我需要的一切,而且速度要快得多! ^.^
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多