广联达钢筋 捕捉不到点:WinPcap基础知识(第四课:不用回调函数来捕捉数据包)

来源:百度文库 编辑:偶看新闻 时间:2024/04/28 18:25:27
这节课程中的例子程序完成的功能和上节课的一样,但是使用的是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   
 
#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->ts.tv_sec);  
        strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);  
          
        printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len);  
    }  
      
    if(res == -1){  
        printf("Error reading the packets: %s\n", pcap_geterr(adhandle));  
        return -1;  
    }  
      
    return 0;  

#define HAVE_REMOTE
#include #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->ts.tv_sec);
        strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
       
        printf("%s,%.6d len:%d\n", timestr, header->ts.tv_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博客,转载请标明出处:http://blog.csdn.net/qsycn/archive/2009/08/18/4458383.aspx