使用winpcap是什么的pcap_sendqueue_transmit函数发送队列,数据包的时间戳必须自己写吗?

WinPcap学习(九)发送数据包
WinPcap学习(九)发送数据包
原始的libcap库是不支持发送数据包的,因此,这是属于WinPcap的扩展。
使用pcap_sendpacket()发送单个数据包
打开适配器以后,调用pcap_sendpacket()来发送手工制作的数据包。pcap_sendpacket()的参数有一个要包涵发送数据的缓冲区,缓冲的长度,以及用来发送数据的适配器。注意,缓冲数据将直接发送到网络,而不会进行任何加工和处理。这就意味着应用程序需要创建一个正确的协议首部,来使这个数据包更有意义。
#include &stdlib.h&
#include &stdio.h&
#include &pcap.h&
void main(int argc, char **argv)
char errbuf[PCAP_ERRBUF_SIZE];
u_char packet[100];
/* 检查命令行参数的合法性 */
if (argc != 2)
printf(&usage: %s interface (e.g. 'rpcap://eth0')&, argv[0]);
/* 打开输出设备 */
if ( (fp= pcap_open(argv[1],
// 要捕获的部分 (只捕获前100个字节)
PCAP_OPENFLAG_PROMISCUOUS,
// 混杂模式
// 读超时时间
// 远程机器验证
// 错误缓冲
) ) == NULL)
fprintf(stderr,&\nUnable to open the adapter. %s is not supported by WinPcap\n&, argv[1]);
/* 假设在以太网上,设置MAC的目的地址为 1:1:1:1:1:1 */
packet[0]=1;
packet[1]=1;
packet[2]=1;
packet[3]=1;
packet[4]=1;
packet[5]=1;
/* 设置MAC源地址为 2:2:2:2:2:2 */
packet[6]=2;
packet[7]=2;
packet[8]=2;
packet[9]=2;
packet[10]=2;
packet[11]=2;
/* 填充剩下的内容 */
for(i=12;i&100;i++)
packet[i]=i%256;
/* 发送数据包 */
if (pcap_sendpacket(fp, packet, 100 /* size */) != 0)
fprintf(stderr,&\nError sending the packet: \n&, pcap_geterr(fp));
pcap_sendpacket()提供了一种简单而直接的方法来发送单个数据包,而send queues则提供了一种高级的、强大的,结构更优的方法来发送一组数据包。发送队列是一个容器,它能容纳不同数量的数据包,这些数据包将被发送到网络上。队列有大小,它代表了它能存储的数据包的最大数量。
发送队列通过调用pcap_sendqueue_alloc()函数创建,并且需要指定队列的大小。
一旦发送队列被创建,pcap_sendqueue_queue()就可以将数据包添加到发送队列中。这个函数的参数包含一个pcap_pkthdr的结构体,它包含时间戳和长度,同时,参数还包含一个指向数据包数据的缓冲。这些参数和那些被pcap_next_ex()和pcap_handler()接收到的数据相同,因此,为那些刚刚捕获到的,或是从文件读出来的数据包排队,就相当于把三个参数传递给pcap_sendqueue_queue()。
WinPcap提供了pcap_sendqueue_transmit()函数来发送一个队列。请注意第三个参数:如果非零,那么发送过程将是同步进行,也就说,只有时间戳相符的数据包才会被处理。这个操作需要消耗大量的CPU资源,因为同步操作由内核驱动中的“忙等”循环来实现。尽管这个操作对CPU的要求很高,但它对包传送的处理结果,通常是很精确的。
请注意,使用pcap_sendqueue_transmit()要比pcap_sendpacket()来发送一系列数据更加有效,因为发送队列保存在内核级的缓冲区,因些,减少了上下文交换的次数。
当队列不需要时,我们可以使用pcap_sendqueue_destroy()来释放它所占用的内存。
下面的程序,先用pcap_open_offline()打开一个捕获文件,然后,将文件中的数据包移到已分配的发送队列。这时,就可以发送队列了,如果用户指定了同步,那么它将同步发送队列。
* Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
* Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Politecnico di Torino, CACE Technologies
* nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CO***IBUTORS
* &AS IS& AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CO***IBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CO***ACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include &stdlib.h&
#include &stdio.h&
#include &pcap.h&
#include &remote-ext.h&
void usage();
void main(int argc, char **argv)
pcap_t *indesc,*
char errbuf[PCAP_ERRBUF_SIZE];
char source[PCAP_BUF_SIZE];
int caplen,
pcap_send_queue *
struct pcap_pkthdr *
float cpu_
u_int npacks = 0;
/* 检查命令行参数的合法性 */
if (argc &= 2 || argc &= 5)
/* 获取捕获文件长度 */
capfile=fopen(argv[1],&rb&);
if(!capfile){
printf(&Capture file not found!\n&);
fseek(capfile , 0, SEEK_END);
caplen= ftell(capfile)- sizeof(struct pcap_file_header);
fclose(capfile);
/* 检查时间戳是否合法 */
if(argc == 4 && argv[3][0] == 's')
sync = TRUE;
sync = FALSE;
/* 开始捕获 */
/* 根据WinPcap的新语法创建一个源字符串 */
if ( pcap_createsrcstr( source,
// 源字符串
PCAP_SRC_FILE,
// 我们要打开的文件
// 远程主机
// 远程主机的端口
// 我们要打开的文件名
// 错误缓冲
fprintf(stderr,&\nError creating a source string\n&);
/* 打开捕获文件 */
if ( (indesc= pcap_open(source, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf) ) == NULL)
fprintf(stderr,&\nUnable to open the file %s.\n&, source);
/* 打开要输出的适配器 */
if ( (outdesc= pcap_open(argv[2], 100, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf) ) == NULL)
fprintf(stderr,&\nUnable to open adapter %s.\n&, source);
/* 检查MAC的类型 */
if (pcap_datalink(indesc) != pcap_datalink(outdesc))
printf(&Warning: the datalink of the capture differs from the one of the selected interface.\n&);
printf(&Press a key to continue, or CTRL+C to stop.\n&);
getchar();
/* 分配发送队列 */
squeue = pcap_sendqueue_alloc(caplen);
/* 从文件中将数据包填充到发送队列 */
while ((res = pcap_next_ex( indesc, &pktheader, &pktdata)) == 1)
if (pcap_sendqueue_queue(squeue, pktheader, pktdata) == -1)
printf(&Warning: packet buffer too small, not all the packets will be sent.\n&);
if (res == -1)
printf(&Corrupted input file.\n&);
pcap_sendqueue_destroy(squeue);
/* 发送队列 */
cpu_time = (float)clock ();
if ((res = pcap_sendqueue_transmit(outdesc, squeue, sync)) & squeue-&len)
printf(&An error occurred sending the packets: %s. Only %d bytes were sent\n&, pcap_geterr(outdesc), res);
cpu_time = (clock() - cpu_time)/CLK_TCK;
printf (&\n\nElapsed time: %5.3f\n&, cpu_time);
printf (&\nTotal packets generated = %d&, npacks);
printf (&\nAverage packets per second = %d&, (int)((double)npacks/cpu_time));
printf (&\n&);
/* 释放发送队列 */
pcap_sendqueue_destroy(squeue);
/* 关闭输入文件 */
pcap_close(indesc);
* 释放输出适配器
* IMPORTANT: 记得一定要关闭适配器,不然就不能保证
* 所有的数据包都回被发送出去
pcap_close(outdesc);
void usage()
printf(&\nSendcap, sends a libpcap/tcpdump capture file to the net. Copyright (C) 2002 Loris Degioanni.\n&);
printf(&\nUsage:\n&);
printf(&\t sendcap file_name adapter [s]\n&);
printf(&\nParameters:\n&);
printf(&\nfile_name: the name of the dump file that will be sent to the network\n&);
printf(&\nadapter: the device to use. Use \&WinDump -D\& for a list of valid devices\n&);
printf(&\ns: if present, forces the packets to be sent synchronously, i.e. respecting the timestamps in the dump file. This option will work only under Windows NTx.\n\n&);
我的热门文章
即使是一小步也想与你分享深度剖析WinPcap之(九)----数据包的发送过程(2)
重复发送单个数据包的示例
我们采用实际代码演示如何重复发送单个数据包。在send工程的main.cpp添加下面的代码:[send_n工程]
#include &pcap-int.h&
//重复50次
PacketSetNumWrites((LPADAPTER)(adhandle-&adapter),50);
同时给Linker-&Input-&Additional
Dependencies添加工程依赖的库文件Packet.dll,同时从WinPcap库源代码wpcap\libpcap目录下复制pcap-int.***件到F:\WpdPack\Include目录下。
运行示例程序,用Wireshark接收示例程序所发送的数据包如图9-3所示。
Wireshark所接收的数据包
使用发送队列发送数据包的示例(同步方式)
我们采用实际代码演示如何通过pcap_sendqueue_transmit函数以同步方式发送大量数据包。在main()函数中选择适合的适配器,确定发送数据包的个数为100,每个数据包之间的时间间隔dus为20微秒,然后调用应用程序的send_queue函数发送数据包。
send_queue(adhandle,100,20);
示例程序代码如下:[send_queue工程]
#define WIN32
#define H***E_REMOTE
#include &stdio.h&
#include "pcap.h"
#include "Win32-Extensions.h"
void send_queue(pcap_t *fp,unsigned int
npacks,unsigned int dus);
void genPacket(unsigned
char *buf,int len);
timeval add_stamp(timeval *ptv,unsigned int
int main()
pcap_if_t *
pcap_if_t *d;
errbuf[PCAP_ERRBUF_SIZE];
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL,
&alldevs, errbuf) == -1)
fprintf(stderr,"Error in
pcap_findalldevs:
d=d-&next)
printf("%d. %s", ++i,
(d-&description)
&&&&&&&&&&&
printf(" (%s)\n",
d-&description);
&&&&&&&&&&&
printf(" (No description
available)\n");
printf("\nNo interfaces
Make sure WinPcap is installed.\n");
return -1;
printf("Enter the interface number
(1-%d):",i);
scanf("%d",
if(inum & 1 || inum
printf("\nInterface number out of
range.\n");
pcap_freealldevs(alldevs);
return -1;
for(d=alldevs, i=0;
i& inum-1 ;d=d-&next,
if ( (adhandle=
pcap_open(d-&name, 65536,&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&PCAP_OPENFLAG_PROMISCUOUS,
NULL, errbuf& ) ) ==
fprintf(stderr,"\nUnable to open the
%s is not supported by WinPcap\n", d-&name);
pcap_freealldevs(alldevs);
return -1;
printf("\nlistening on %s...\n",
d-&description);
send_queue(adhandle,100,20);
pcap_close(adhandle);
pcap_freealldevs(alldevs);
函数send_queue 负责生成发送队列与发送发送队列,代码具体实现如下:
void send_queue(pcap_t *fp,unsigned int
npacks,unsigned int dus)
errbuf[PCAP_ERRBUF_SIZE];
unsigned int&&&
pcap_send_queue *&&&&&&&
//发送队列&&
const int MaxPacketLen=100;&&&&
//数据包长度
struct pcap_pkthdr
//数据包的包头
struct pcap_pkthdr
pktheader=&
&&&&&&&&&&&&&&&&&&
tv.tv_sec=0;
tv.tv_usec=0;
//分配发送队列
squeue=pcap_sendqueue_alloc(
(unsigned int)(
(MaxPacketLen+sizeof(struct
pcap_pkthdr))*npacks)
//用数据包填充发送队列
unsigned char *pBuf=new unsigned
char[MaxPacketLen];
for(i=0;i&i++)
memset(pBuf,0x0,MaxPacketLen);
//获得生成的数据包,长度为MaxPacketLen
genPacket(pBuf,MaxPacketLen);
//设置数据包的包头
pktheader-&ts=
pktheader-&caplen = MaxPacketL
pktheader-&len = MaxPacketL
if (pcap_sendqueue_queue(squeue,
pktheader, pBuf) == -1)
&&&&&&printf("警告: 数据包缓冲区太小,
不是所有的数据包被发送.\n");
&&&&&&&&&&&
add_stamp(&tv,dus);& //增加时间戳
pktheader-&ts= &&
//更新数据包头的时间戳
delete [] pB
//发送数据包
if ((res = pcap_sendqueue_transmit(fp, squeue,
squeue-&len)//同步发送
&&&&&printf("发送数据包时出现错误:%s. 仅%d字节被发送\n",
&&&&&&&&&&
pcap_geterr(fp), res);
//释放发送队列
pcap_sendqueue_destroy(squeue);
return;&&&
函数add_stamp增加时间戳,参数ptv修改前后的时间戳结构体指针,参数dus为时间增加的微秒数。函数源代码如下:
timeval add_stamp(timeval *ptv,unsigned int
ptv-&tv_usec=ptv-&tv_usec+&
if(ptv-&tv_usec&=1000000)
ptv-&tv_sec=ptv-&tv_sec+1;
ptv-&tv_usec=ptv-&tv_usec-1000000;
用Wireshark接收示例程序所发送的数据包如图9-4所示。
Wireshark所接收的数据包
在Wireshark概要区域的Time字段中可见,接收的时间戳间隔为20微秒,精度差别为2微秒左右,100个数据包总共耗费1966微秒(理论上应该为20*(100-1)=1980微秒);协议Protocol字段显示为0x0c0d。
在Wireshark详情区域中可看到目标MAC地址为01:01:01:01:01:01,源MAC地址为02:02:02:02:02:02。
从Wireshark数据区域中可看到数据包的内容从0开始递增只到0x55(十进制85)。
本文出自 “” 博客,请务必保留此出处
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。深度剖析WinPcap之(九)——数据包的发送过程
核心提示:
为发送数据包,一个用户层应用程序在NPF设备上执行一个WriteFile()系统调用,深度剖析WinPcap之(九)——数据包的发送过程(2),这样发送每一个数据包都需要一次系统调用,网络数据包的发送效率并不是非常高,该函数原型如下:intpcap_sendqueue_queue(pcap_se
为发送数据包,一个用户层应用程序在NPF设备上执行一个WriteFile()系统调用。这样发送每一个数据包都需要一次系统调用,网络数据包的发送效率并不是非常高。因为该原因,WinPcap添加了使用一次写系统调用就能把单个数据包发送多次的功能。用户层应用程序能够设置单个数据包发送的次数,例如设为1000,那么应用程序所写的每个原始数据包在驱动设备文件上都将会发送1000次。不过该功能只在packet.dll中提供辅助接口函数PacketSetNumWrites设置发送次数,而在wpcap.dll中并没有对应的函数接口。应用程序能够用该特性为测试的目的生成高速的网络流量:上下文切换的负载不再出现,因此性能显著性的变好。在上述两种发送方式都不适用的情况下,为了能够发送大量的数据包,WinPcap提供了基于发送队列发送的方式。通过发送队列提供了一种高级的,强大的,结构更优的方式来发送一组数据包。发送队列通过调用 pcap_sendqueue_alloc函数创建,并且需要指定队列的大小。pcap_send_queue* pcap_sendqueue_alloc(u_int memsize);该函数分配一个发送队列。发送队列是一个容器,它能容纳不同数量的数据包,这些数据包将被pcap_sendqueue_transmit函数发送到网络上。其中参数memsize是队列的大小,用以字节为单位,决定了发送队列能存储数据包的最大容量。 一旦发送队列被创建,就可以通过pcap_sendqueue_queue函数将数据包添加到发送队列中。该函数原型如下:int pcap_sendqueue_queue(pcap_send_queue *queue,const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)  该函数把一个数据包添加到queue参数所指的发送队列的尾部。参数pcap_pkthdr结构体包含数据包的时间戳和长度,参数pkt_data是一个指向数据包数据的缓冲区的指针。
赞助商链接winpcap 在windows下,利用 拦截数据包,并且获得 的时间戳 WinSock-NDIS 网络编程 238万源代码下载-
&文件名称: winpcap
& & & & &&]
&&所属分类:
&&开发工具: Visual C++
&&文件大小: 1747 KB
&&上传时间:
&&下载次数: 20
&&提 供 者:
&详细说明:在windows下,利用winpcap拦截数据包,并且获得拦截数据包的时间戳-In the windows, the use winpcap packet intercept and get the timestamp of the packet intercept
文件列表(点击判断是否您需要的文件,如果是垃圾请在下面评价投诉):
&&winpcap&&.......\Debug&&.......\.....\vc60.idb&&.......\.....\vc60.pdb&&.......\.....\winpcap.exe&&.......\.....\winpcap.ilk&&.......\.....\winpcap.obj&&.......\.....\winpcap.pch&&.......\.....\winpcap.pdb&&.......\winpcap.c&&.......\winpcap.dsp&&.......\winpcap.dsw&&.......\winpcap.ncb&&.......\winpcap.opt&&.......\winpcap.plg
&近期下载过的用户:
&输入关键字,在本站238万海量源码库中尽情搜索:
&[] - LSP拦截完整代码
lsp列表显示,加载,删除
&[] - 一个用VC实现的简单windows防火墙,拥有拦截IP、分析报文、黑名单等功能
&[] - 利用wincap 发送udp数据包,可以修改源磅IP
&[] - 本文对网络嗅探器***技术的原理和实现进行了比较详细的介绍,讨论了***技术在Windows下的多种实现,并主要介绍了如何在Win32环境中利用Winpcap开发包开发网络实时***程序,给出了具体的设计与实现方法。详细描述Winpcap开发包的主要功能,分析网络***程序的层次结构(从底到顶依次为NPF驱
&[] - 利用WinPcap开发数据报文捕获和统计程序,能够统计一段时间内网络中的协议数据,获得统计结果(IP:?包,TCP:?包,UDP:?包,ICMP:?包)。
&[] - 一个监控POP3上的电子邮件收发的VC源程序,没有什么特别的,就是想给初学者一个示例
&[] - winpcap源码 网络封包拦截 对网络监控的研究人员有所帮助
&[] - 时间戳,是指文件属性里的创建、修改、访问的时间。数字时间戳技术是数字签名技术一种变种的应用。

参考资料

 

随机推荐