分享

libpcap-第四课:不用回调函数来捕捉数据包 - 我的文章 - 汪汪学D

 jijo 2008-10-23



libpcap-第四课:不用回调函数来捕捉数据包
 

第四课:不用回调函数来捕捉数据包

     这节课举的例子很象上节课的例子(获得已经安装设备的高级信息),但是这个例子我们用的是函数pcap_next_ex()而不是用pcap_loop()

     在某些情况下面,基于回调函数来捕获数据包的pcap_loop()方面是很好的选择,但是,处理一个回调函数有时候是不现实的。通常它会使得程序变得非常复杂并且在多线程应用程序或者在C++类里面它会成为一块心病。

     pcap_next_ex()方法可以让我们直接调用来获得数据包。使用pcap_next_ex()可以获得程序的完全控制,因为仅仅在程序要捕获数据包的时候数据包才会接收。

     在下面的程序里面,调用完pcap_next_ex(),我们重复使用上次课例子里面的回调函数代码,然后在main函数里面去掉他们。

函数  int pcap_next_ex  (  pcap_t *  p, 

              struct pcap_pkthdr **  pkt_header, 

              const u_char **  pkt_data  )

作用:从一个接口上面读取数据包或者从一个离线捕捉中读取数据包。该函数经常用来获取下一个可用的数据包,而避免使用LibPcap提供的传统的使用回调函数的方法。

参数:

       pcap_t * 在头文件里面有定义:pcap_t就是pcap的别名。

       参数前面都已经出现过,这里就不做详细介绍了。

返回值:

       返回1:如果读取数据包没有出现错误。

       返回0:如果pcap_open_live()设置的timeout时间到了。此时,ptk_headerpkt_data不会指向一个合法的数据包。

       返回-1:发生错误

       返回-2:从一次离线捕获中读取数据遇到了EOF 

Code

00001 #include "pcap.h"
                                                

00002
                                                

00003
                                                

00004 main()
                                                

00005 {
                                                

00006 pcap_if_t *alldevs;
                                                

00007 pcap_if_t *d;
                                                

00008 int inum;
                                                

00009 int i=0;
                                                

00010 pcap_t *adhandle;
                                                

00011 int res;
                                                

00012 char errbuf[PCAP_ERRBUF_SIZE];
                                                

00013 struct tm *ltime;
                                                

00014 char timestr[16];
                                                

00015 struct pcap_pkthdr *header;
                                                

00016 u_char *pkt_data;
                                                

00017     
                                                

00018     
                                                

00019     /* Retrieve the device list on the local machine */
                                                

00020     if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
                                                

00021     {
                                                

00022         fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
                                                

00023         exit(1);
                                                

00024     }
                                                

00025     
                                                

00026     /* Print the list */
                                                

00027     for(d=alldevs; d; d=d->next)
                                                

00028     {
                                                

00029         printf("%d. %s", ++i, d->name);
                                                

00030         if (d->description)
                                                

00031             printf(" (%s)\n", d->description);
                                                

00032         else
                                                

00033             printf(" (No description available)\n");
                                                

00034     }
                                                

00035     
                                                

00036     if(i==0)
                                                

00037     {
                                                

00038         printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
                                                

00039         return -1;
                                                

00040     }
                                                

00041     
                                                

00042     printf("Enter the interface number (1-%d):",i);
                                                

00043     scanf("%d", &inum);
                                                

00044     
                                                

00045     if(inum < 1 || inum > i)
                                                

00046     {
                                                

00047         printf("\nInterface number out of range.\n");
                                                

00048         /* Free the device list */
                                                

00049         pcap_freealldevs(alldevs);
                                                

00050         return -1;
                                                

00051     }
                                                

00052     
                                                

00053     /* Jump to the selected adapter */
                                                

00054     for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
                                                

00055     
                                                

00056     /* Open the device */
                                                

00057     if ( (adhandle= pcap_open(d->name,          // name of the device
                                                

00058                               65536,            // portion of the packet to capture. 
                                                

00059                                                 // 65536 guarantees that the whole packet will be captured on all the link layers
                                                

00060                               PCAP_OPENFLAG_PROMISCUOUS,    // promiscuous mode
                                                

00061                               1000,             // read timeout
                                                

00062                               NULL,             // authentication on the remote machine
                                                

00063                               errbuf            // error buffer
                                                

00064                               ) ) == NULL)
                                                

00065     {
                                                

00066         fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
                                                

00067         /* Free the device list */
                                                

00068         pcap_freealldevs(alldevs);
                                                

00069         return -1;
                                                

00070     }
                                                

00071     
                                                

00072     printf("\nlistening on %s...\n", d->description);
                                                

00073     
                                                

00074     /* At this point, we don't need any more the device list. Free it */
                                                

00075     pcap_freealldevs(alldevs);
                                                

00076     
                                                

00077     /* Retrieve the packets */
                                                

00078     while((res = pcap_next_ex( adhandle, &header, &pkt_data)) >= 0){
                                                

00079         
                                                

00080         if(res == 0)
                                                

00081             /* Timeout elapsed */
                                                

00082             continue;
                                                

00083         
                                                

00084         /* convert the timestamp to readable format */
                                                

00085         ltime=localtime(&header->ts.tv_sec);
                                                

00086         strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
                                                

00087         
                                                

00088         printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len);
                                                

00089     }
                                                

00090     
                                                

00091     if(res == -1){
                                                

00092         printf("Error reading the packets: %s\n", pcap_geterr(adhandle));
                                                

00093         return -1;
                                                

00094     }
                                                

00095     
                                                

00096     return 0;
                                                

00097 }
                                                

程序运行说明:按照前面所说的加上宏定义即可。
                                                

疑问:没有完全体现出好控制的特征
                                                

感觉也只是点点,可以设置一个变量,来控制是否接收下一个数据包,这点还是可以做到得,不过这里是因为数据包太多了,一般不会出现问题。关于pcap_next_ex()方法,文档里面没有介绍是阻塞得还是非阻塞,个人认为是阻塞得,也就是说从开始执行,一直倒接收倒一个包才返回。尽管这里是阻塞得,但是设置一个变量每次检查一下,看看是否是用户要求关闭接收,这个操作还是没什么问题。不会出现虽然用户设置了停止阻塞得标志位,但是由于此方法是阻塞的,因为等不到数据包而一直没有响应用户,因为这里有一个事实大家应该明白,网上发送的数据包时时刻刻都在。
                                                








    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多