深度剖析WinPcap之(九)――数据包的发送过程(13-2)

-------------------------继续----------------------------
       if ( Sync ){/* 处理与时间戳的同步发送 */
          
// 如果需要阻塞超过约 1 秒,释放应用程序
           if( winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec > 1 )
           {     
              // 等待挂起的发送完成
              NPF_WaitEndOfBufferedWrite(Open);
              NPF_StopUsingBinding(Open);
              return (INT)((PCHAR)winpcap_hdr - UserBuff);
           }         
      
// 计算在发送下一个数据包之前等待的时间间隔
           TargetTicks.QuadPart = StartTicks.QuadPart +
(LONGLONG)(
(winpcap_hdr->ts.tv_sec –
BufStartTime.tv_sec) * 1000000 +
winpcap_hdr->ts.tv_usec - BufStartTime.tv_usec) *
(TimeFreq.QuadPart
)/1000000;
          
           // 等待直到时间间隔逝去
           while ( CurTicks.QuadPart <= TargetTicks.QuadPart )
              CurTicks = KeQueryPerformanceCounter(NULL);
       }  
    }
 
   
    NPF_StopUsingBinding(Open);
    // 返回已发送的字节数
    return (INT)((PCHAR)winpcap_hdr - UserBuff);
}
函数PacketSendPackets通过NPF_IoControl函数调用 NPF_BufferedWrite 函数时需要考虑下列两个问题的处理:
Ø         数据包队列并不一定是一次全部传递给内核,可能分几次,所以 NPF_BufferedWrite 函数 需要返回的字节大小需要进行头部对齐。
Ø         延迟时间的处理。
    PacketSendPackets NPF_BufferedWrite 两个函数中都能看见如下所示的类似的忙等待代码。
INT PacketSendPackets(LPADAPTER AdapterObject,
PVOID PacketBuff, ULONG Size, BOOLEAN Sync)
{
// 等待时间间隔的逝去
    while( CurTicks.QuadPart <= TargetTicks.QuadPart )
       QueryPerformanceCounter(&CurTicks);
}
 
INT NPF_BufferedWrite(
    IN PIRP Irp,
    IN PCHAR UserBuff,
    IN ULONG UserBuffSize,
    BOOLEAN Sync)
{
// 等待直到时间间隔逝去
    while( CurTicks.QuadPart <= TargetTicks.QuadPart )
       CurTicks = KeQueryPerformanceCounter(NULL);
   
}  
对于发送队列发送方式的时间间隔的 图示如下图:
9-7 等待时间间隔示意图
NPF_BufferedWrite函数中处理每个包之间的时间间隔,而在 PacketSendPackets 函数中处理每块数据包之间的时间间隔,这与第一个问题相关。这也就是在PacketSendPackets NPF_BufferedWrite 两个函数中都能看见类似的忙等待代码的原因之所在。

你可能感兴趣的:(职场,休闲,winpcap)