zoukankan      html  css  js  c++  java
  • Winpcap笔记4之不用回调函数捕获数据包

    函数1:

    pcap_next_ex(pcap_t*                       p,

                          struct pcap_pkthdr**   pkt_header,

                          const u_char*             pkt_data

    )

        从一个网络接口或离线捕获方式(例如读文件)读取一个数据包。该函数被用来重新获得下一个可用的数据包,没有使用libpcap提供的传统的回调方法。pcap_next_ex用指向头和下一个被捕获的数据包的指针为pkt_header和pkt_data参数赋值。

    返回值有下列几种情况:

    1,数据包被正确读取

    0,pcap_open_live()设置的超时时间到。在这种情况下pkt_header和pkt_data不指向有效数据包

    -1,发生错误

    -2,离线捕获的时候读取到EOF

        我们通常使用pcap_next_ex()而不是pcap_next(),因为pcap_next()有些缺点。首先,pcap_next()效率低,因为它隐藏了回调方法但是还是依赖于pcap_dispatch;第二,它不能检测EOF,所以当从一个文件获取数据包时它不是很有用。

    函数2:

    u_char* pcap_next(pcap_t*                      p,

    struct pcap_pkthdr*     h

    )

        返回下一个可用的数据包并且返回一个u_char指向该数据包数据部分的指针。如果发生错误或者活动的抓包没有读取到数据包(例如:数据包不能通过包过滤器而被丢弃,或者在支持读超时(read timeout)的平台上在任何数据包到来之前就超时终止,又或者是抓包设备的文件描述符在非阻塞(non-blocking)模式下并且没有数据包可以被读取),或者文件已被读完时返回NULL。不幸的是,没有办法检测是否发生错误。

     Winpcap提供(libpcap也提供)的一个强大特性是过滤引擎(filtering engine)。它提供了一个非常有效的接收网络流量的方法,并且它通常与Winpcap提供的抓包机制集成在一起。用于过滤数据包的函数是pcap_complie()和pcap_setfilter()。

         pcap_complie()使用一个包含高级布尔表达式的字符串并且产生一个能被过滤引擎集成到数据包驱动中的低级字节码。

         pcap_setfilter()把一个过滤器与核心驱动抓包会话关联起来。一旦pcap_setfilter()被调用,相关的过滤器将被应用到所有的来自网络的数据包上,并且所有的一致的数据包将被复制给应用程序。

      1 //不用回掉函数捕获数据包
      2 #include "pcap.h"
      3 
      4 
      5 int main()
      6 {
      7     pcap_if_t *alldevs;
      8     pcap_if_t *d;
      9     int inum;
     10     int i = 0;
     11     pcap_t *adhandle;
     12     int res;
     13     char errbuf[PCAP_ERRBUF_SIZE];
     14     struct tm *ltime;
     15     char timestr[16];
     16     struct pcap_pkthdr *header;
     17     const u_char *pkt_data;
     18     time_t local_tv_sec;
     19 
     20 
     21     /* 获取本机设备列表 */
     22     if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
     23     {
     24         fprintf(stderr, "Error in pcap_findalldevs: %s
    ", errbuf);
     25         exit(1);
     26     }
     27 
     28     /* 打印列表 */
     29     for (d = alldevs; d; d = d->next)
     30     {
     31         printf("%d. %s", ++i, d->name);
     32         if (d->description)
     33             printf(" (%s)
    ", d->description);
     34         else
     35             printf(" (No description available)
    ");
     36     }
     37 
     38     if (i == 0)
     39     {
     40         printf("
    No interfaces found! Make sure WinPcap is installed.
    ");
     41         return -1;
     42     }
     43 
     44     printf("Enter the interface number (1-%d):", i);
     45     scanf("%d", &inum);
     46 
     47     if (inum < 1 || inum > i)
     48     {
     49         printf("
    Interface number out of range.
    ");
     50         /* 释放设备列表 */
     51         pcap_freealldevs(alldevs);
     52         return -1;
     53     }
     54 
     55     /* 跳转到已选中的适配器 */
     56     for (d = alldevs, i = 0; i < inum - 1; d = d->next, i++);
     57 
     58     /* 打开设备 */
     59     if ((adhandle = pcap_open(d->name,          // 设备名
     60         65536,            // 要捕捉的数据包的部分 
     61         // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容
     62         PCAP_OPENFLAG_PROMISCUOUS,    // 混杂模式
     63         1000,             // 读取超时时间
     64         NULL,             // 远程机器验证
     65         errbuf            // 错误缓冲池
     66         )) == NULL)
     67     {
     68         fprintf(stderr, "
    Unable to open the adapter. %s is not supported by WinPcap
    ", d->name);
     69         /* 释放设列表 */
     70         pcap_freealldevs(alldevs);
     71         return -1;
     72     }
     73 
     74     printf("
    listening on %s...
    ", d->description);
     75 
     76     /* 释放设备列表 */
     77     pcap_freealldevs(alldevs);
     78 
     79     /* 获取数据包 */
     80     while ((res = pcap_next_ex(adhandle, &header, &pkt_data)) >= 0){
     81 
     82         if (res == 0)
     83             /* 超时时间到 */
     84             continue;
     85 
     86         /* 将时间戳转换成可识别的格式 */
     87         local_tv_sec = header->ts.tv_sec;
     88         ltime = localtime(&local_tv_sec);
     89         strftime(timestr, sizeof timestr, "%H:%M:%S", ltime);
     90 
     91         printf("%s,%.6d len:%d
    ", timestr, header->ts.tv_usec, header->len);
     92     }
     93 
     94     if (res == -1){
     95         printf("Error reading the packets: %s
    ", pcap_geterr(adhandle));
     96         return -1;
     97     }
     98 
     99     return 0;
    100 }
  • 相关阅读:
    剑指offer23-二叉搜索树的后序遍历序列
    剑指offer24-二叉树中和为某一值的路径
    剑指offer-复杂链表的复制
    剑指offer-二叉搜索树与双向链表
    剑指offer-字符串的排序
    剑指offer-数组中出现次数超过一半的数字
    剑指offer-最小的k个数
    c++中参数加&与不加的区别
    第九届蓝桥杯(A组填空题)
    基于优先级的多道程序系统作业调度——基于优先级
  • 原文地址:https://www.cnblogs.com/lanjianhappy/p/6667275.html
Copyright © 2011-2022 走看看