WinPcap基础知识(第四课:不用回调函数来捕捉数据包)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

WinPcap基础知识(第四课:不用回调函数来捕捉数据包)
这节课程中的例子程序完成的功能和上节课的一样,但是使用的是pcap_next_ex()而不是pcap_loop().
基于回调捕获机制的pcap_loop()是非常优雅的,在很多情况下都是一个不错的选择。

不过,有时候处理一个回调函数显得不太现实 --- 通常这会使程序更加复杂,在使用多线程或者c++类的时候尤其如此。

在这种情况下,可以直接调用 pcap_next_ex() 来返回一个数据包-- 这样程序员可以在仅仅想使用它们的时候再处理 pcap_next_ex() 返回的数据包。

这个函数的参数和回调函数 pcap_loop() 的一样 -- 由一个网络适配器描述符作为入口参数和两个指针作为出口参数,这两个指针将在函数中被初始化,然后再返回给用户(一个指向pcap_pkthdr 结构,另一个指向一个用作数据缓冲区的内存区域)。

在下面的程序中,我们继续使用上一节课中的例子的数据处理部分的代码,把这些代码拷贝到main()函数中pcap_next_ex()的后面。

view plaincopy to clipboardprint?
#define HAVE_REMOTE
#include <pcap.h>
#pragma comment(lib,"wpcap.lib")
main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int inum;
int i=0;
pcap_t *adhandle;
int res;
char errbuf[PCAP_ERRBUF_SIZE];
struct tm *ltime;
char timestr[16];
struct pcap_pkthdr *header;
u_char *pkt_data;
/* Retrieve the device list on the local machine */
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}
/* Print the list */
for(d=alldevs; d; d=d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)\n", d->description);
else
printf(" (No description available)\n");
}
if(i==0)
{
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
return -1;
}
printf("Enter the interface number (1-%d):",i);
scanf("%d", &inum);
if(inum < 1 || inum > i)
{
printf("\nInterface number out of range.\n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}
/* Jump to the selected adapter */
for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
/* Open the device */
if ( (adhandle= pcap_open(d->name, // name of the device
65536, // portion of the packet to capture.
// 65536 guarantees that the whole packet will be captured on all the link layers
PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode 1000, // read timeout
NULL, // authentication on the remote machine
errbuf // error buffer
) ) == NULL)
{
fprintf(stderr,"\nUnable to open the adapter. %s is not
supported by WinPcap\n", d->name);
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}
printf("\nlistening on %s...\n", d->description);
/* At this point, we don't need any more the device list. Free it */
pcap_freealldevs(alldevs);
/* Retrieve the packets */
while((res = pcap_next_ex( adhandle, &header, (const u_char**)&pkt_data)) >= 0){
if(res == 0)
/* Timeout elapsed */
continue;
/* convert the timestamp to readable format */
ltime=localtime(&header->_sec);
strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
printf("%s,%.6d len:%d\n", timestr, header->_usec, header->len);
}
if(res == -1){
printf("Error reading the packets: %s\n",
pcap_geterr(adhandle));
return -1;
}
return 0;
}
#define HAVE_REMOTE
#include <pcap.h>
#pragma comment(lib,"wpcap.lib")
main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int inum;
int i=0;
pcap_t *adhandle;
int res;
char errbuf[PCAP_ERRBUF_SIZE];
struct tm *ltime;
char timestr[16];
struct pcap_pkthdr *header;
u_char *pkt_data;
/* Retrieve the device list on the local machine */
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}
/* Print the list */
for(d=alldevs; d; d=d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)\n", d->description);
else
printf(" (No description available)\n");
}
if(i==0)
{
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
return -1;
}
printf("Enter the interface number (1-%d):",i);
scanf("%d", &inum);
if(inum < 1 || inum > i)
{
printf("\nInterface number out of range.\n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}
/* Jump to the selected adapter */
for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
/* Open the device */
if ( (adhandle= pcap_open(d->name, // name of the device
65536, // portion of the packet to capture.
// 65536 guarantees that the whole packet will be captured on all the link layers
PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode 1000, // read timeout
NULL, // authentication on the remote machine
errbuf // error buffer
) ) == NULL)
{
fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}
printf("\nlistening on %s...\n", d->description);
/* At this point, we don't need any more the device list. Free it */
pcap_freealldevs(alldevs);
/* Retrieve the packets */
while((res = pcap_next_ex( adhandle, &header, (const
u_char**)&pkt_data)) >= 0){
if(res == 0)
/* Timeout elapsed */
continue;
/* convert the timestamp to readable format */
ltime=localtime(&header->_sec);
strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
printf("%s,%.6d len:%d\n", timestr, header->_usec, header->len);
}
if(res == -1){
printf("Error reading the packets: %s\n", pcap_geterr(adhandle));
return -1;
}
return 0;
}
疑问:没有完全体现出好控制的特征
感觉也只是点点,可以设置一个变量,来控制是否接收下一个数据包,这点还是可以做到得,不过这里是因为数据包太多了,一般不会出现问题。

关于pcap_next_ex()方法,文档里面没有介绍是阻塞得还是非阻塞,个人认为是阻塞得,也就是说从开始执行,一直倒接收倒一个包才返回。

尽管这里是阻塞得,但是设置一个变量每次检查一下,看看是否是用户要求关闭接收,这个操作还是没什么问题。

不会出现虽然
用户设置了停止阻塞得标志位,但是由于此方法是阻塞的,因为等不到数据包而一直没有响应用户,因为这里有一个事实大家应该明白,网上发送的数据包时时刻刻都在。

注意:之所以要使用pcap_next_ex()而不使用pcap_next()是因为pcap_next()有些非常讨厌的限制。

首先,他不是很有效的方法,因为它隐藏了回调方法,但是还是依靠pcap_dispatch()。

第二,它不能探测出EOF,所以在合并文件时它几乎没用。

另外,pcap_next_ex()方法的返回值可以给用户很多的提示,对应的所有可能情况。

本文来自CSDN博客,转载请标明出处:/qsycn/archive/2009/08/18/4458383.aspx。

相关文档
最新文档