关于winpcap的一些认识关于winpcap的一些认识
                                                                          Bill yuan
                                                                                                           2004-9-29
一.Winpcap简介
        Winpcap是UNIX下的libpcap移植到windows下的产物,他是一个free and open source的项目。Winpcap工作于驱动(Driver)层,所以能以很高的效率进行网络操作。
        Winpcap提供了以下强大的功能:
1.捕获原始的数据包
2.设置filter,只捕获自己敢兴趣的数据包
3.方便的把捕获的数据包输出到文件和从文件输入
4.发送原始的数据包
5.统计网络流量
6.…..(其它还有很多,我不知道了)
二.Winpcap的安装使用方法
        1.到http://winpcap.polito.it下载winpcap的安装包,程序员开发包。
      2.执行安装包,这样你的机子就能运行winpcap程序了
      3.解压开发包,在VC的option的include和lib中加入winpcap的
include和lib
4. 在你的程序中加入#include <pcap.h>, #include <remote-ext.h>.然后在工程的setting中加入预定义宏:WPCAP,HAVE_REMOTE.导入wpcap.lib库
      5.就可以编写wpcap程序了
三.Winpcap的一些基本的功能的实现
      一)捕获数据包
               1.     枚举所有的可用的设备[pcap_findalldevs_ex](可选)
               2.     通过名字打开一个设备[pcap_open()]
在这里可以打开一个文件,只是在打开这个文件之前需要通过pcap_createsrcstr创建相应的name string
3.         设置Filter[pcap_compile, pcap_setfilter] (可选)
4.         捕获数据
有几种捕获数据的方法(捕获数据的数据都是最原始的数据包,即包含数据链路层的数据头)
a.  是以回调的方式[ pcap_loop,pcap_dispatch() ].
这两种方法基本相同,底层收集数据包,当满足一定的条件(timeout 或者缓冲区满),就会调用回调函数,把收集到的原始数据包s,交给用户。他们返回的数据缓冲区包含多个包
b.      pcap_next_ex()的方式
每当一个包到到达以后,pcap_next_ex就会返回,返回的数据缓冲区里只包涵一个包。
        二)发送包
               Winpcap中有发送单个包和发送多个包的方法。这里只说说发送单个包
1. 通过名字打开一个设备[pcap_open]
2. 自己构造一个原始数据包(这个数据包会不经过任何处理就发送出去,所以必须把包中的各个字段设置好。另外这个数据包是包含数据链路层报头的)
3. 使用pcap_sendpacket()发送数据包
三)统计网络流量
1. 通过名字打开一个设备[pcap_open]
      通过  read_timeout来设置统计的时间间隔
2. 设置filter[pcap_compile, pcap_setfilter] (可选)
3.  设置设备的为统计模式[ pcap_setmode(MODE_STAT);]
4.  开始统计,pcap_loop/pcap_dispatch()
5.在回调函数中的参数中就包含了统计信息,如下图:
       
     
四. 总结
这些东西都是我在学习winpcap的过程中的一些经验和总结。由于我学习winpcap的时间很匆忙,只是按照step by step guide来学习的,所以我对于winpcap的理解也就只能局限与此,希望能在以后有机会深入学习
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//下面是一个应用winpcap写的一个网络流量统计的例子,
// nettraffic.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <pcap.h>
#include <remote-ext.h>
#include <iostream>
#include <winsock2.h>
using namespace std;
//————————————————————————
//————————————————————————
void dispatcher_handler(u_char* user_data, const struct pcap_pkthdr * pkthdr, const u_char *pktdata);
//————————————————————————
int main(int argc, char* argv[])
{
        int                                        i;
        pcap_if_t*                           alldevs;
        pcap_if_t*                           dev;
        char                              errorbuf[PCAP_ERRBUF_SIZE];
        int                                        choice;
        pcap_t*                               stathandle;
        WSADATA                               wsadata;
        struct timeval                timestamp;
       
        if( WSAStartup( MAKEWORD(2,2), &wsadata) != 0 )
        {
               cerr<<"WSAStartup failed [ "<<WSAGetLastError() <<" ]"<<endl;
               return (-1);
        }
       
        //enum all device
        if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &alldevs, errorbuf ) == -1 )
        {
               WSACleanup();
               cerr<<"pcap_findalldevs_ex failed! ("<<errorbuf<<")"<<endl;
               return (-1);
        }
       
        for( i=0,dev = alldevs; dev != NULL; dev = dev->next )
        {
               cout<<++i<<‘t'<<dev->name<<endl;
        }
       
        if( i== 0 )
        {
               WSACleanup();
               cerr<<"no device found!"<<endl;
               return (-2);
        }
       
        //let user choice
        while( 1)
        {
               cout<<"please choice a device:";
               cin>>choice;
               if( choice >= 1 &&  choice <=i )
                      break;
              
               cerr<<"input error, you shall choice a device from upon list"<<endl;
        }
       
        //move to the choice device
        for( i=0, dev = alldevs; i<choice-1; i++,dev = dev->next );
        if( (stathandle = pcap_open( dev->name,
                                                         100,
                                                         PCAP_OPENFLAG_PROMISCUOUS,
                                                         500,
                                                         NULL, errorbuf ) ) == NULL )
        {
               cerr<<"open device failed! [device:"<<dev->name<<"] "
                      <<errorbuf<<endl;
              
               pcap_freealldevs( alldevs );
               WSACleanup();
               return (-3);
        }
       
        cout<<"is Stat "<<dev->name<<" …"<<endl;
        pcap_freealldevs( alldevs );
       
        pcap_setmode( stathandle, MODE_STAT );
        timestamp.tv_sec = 0;
        timestamp.tv_usec = 0;
        pcap_loop( stathandle, 0, dispatcher_handler,(unsigned char*)×tamp );
        pcap_close( stathandle );
        return 0;
}
//————————————————————————
void dispatcher_handler(u_char* user_data, const struct pcap_pkthdr * pkthdr, const u_char *pktdata)
{
        static struct timeval        tstamp = *( (struct timeval*)user_data );
        LARGE_INTEGER                   Bps,Pps;
        unsigned long                delay;
        char                              strtime[32];
       
        delay = (pkthdr->ts.tv_sec – tstamp.tv_sec)*1000000 – tstamp.tv_usec + pkthdr->ts.tv_usec;
       
        Pps.QuadPart = ((*(LONGLONG*)(pktdata)) * 1000000 ) / delay;
        Bps.QuadPart = ((*(LONGLONG*)(pktdata + 8)) * 1000000 ) / delay;
        struct tm* ltime = localtime( &(pkthdr->ts.tv_sec) );
        strftime( strtime, sizeof(strtime),"%H:%M:%S", ltime);
       
        printf("%s:", strtime );
        printf("tPps=%I64utBps=%I64urn",Pps.QuadPart,Bps.QuadPart);
       
        tstamp = pkthdr->ts;
}