使用Winpcap示例程序的时候,会出现很多错误(转)

使用Winpcap示例程序的时候,会出现很多错误(转)

WINPCAP编程环境设置
2008-05-19 12:41
一、WINPCAP编程环境设置
在正式WinPcap编程之前,要配置运行环境。
1、运行环境设置
Win32 平台下WinPcap应用程序需要以下四个动态链接库才能正常运行:wpcap.dll Packet.dll WanPacket.dll pthreadVC.dll
这四个动态链接库在WinPcap驱动程序里。
如果没有这个驱动程序,需要到WinPcap官方网站上下载,下载地址为:www.WinPcap.org
如果应用程序出现一下提示,那就是没有安装驱动程序的原因了。
也可以不安装WinPcap驱动程序。但是需要把上面提到的四个动态链接库文件拷贝到系统分区/WINDOWS/system32目录下。(似乎有些问题)


2、配置编程环境。
1> WWW.WINPCAP.ORG上下载WINPCAP SDK -WpdPackWinPcap SDk里面包含库文件,头文件,文档文件和一些例子。解压到一个指定的目录。解压缩后把Include目录添加到IDE的包含文件中(VC6.0 Tools->Option->Directory; VS 2003/2005 工具->选项->项目和解决方案/项目->VC++目录); lib目录添加为新的库文件目录(VC6.0 Tools->Option->Directory; VS 2003/2005 工具->选项->项目和解决方案/项目->VC++目录)如下图所示。

2> 如果一个源文件使用了WinPcap提供的库函数,那么就需要在该文件开始的位置添加pcap.h包含文件(或者在引用的文件中),即#include “pcap.h”
也许会出现下面的错误:
fatal error C1083: 无法打开包括文件:“pcap.h”: No such file or directory
这个错误表明找不到pcap.h文件,这个头文件在驱动程序安装完成后也是没有的,它是开发包里面的一个头文件,所以,如果要运行程序还需要到官方网站上去下载WinPcap SDK,并按步骤1添加到项目中。

3> 在程序中添加wpcap.lib。如果出现下面错误
error LNK2019: 无法解析的外部符号_pcap_findalldevs_ex,该符号在函数XXX 中被引用,如果发生上面的错误就表明缺少库文件,需要添加wpcap.lib到工程中(VC6.0 Project->Settings->Link->Object/library modules; VS 2003/2005 项目->添加现有项->所有文件)如下图所示:

4> 新的版本里WinPcap支持远程数据包获取,所以还应当添加一个头文件remote-ext.h ,即#include "remote-ext.h"(记住这条语句要放在#include “pcap.h”之后,否则会出错!)
否则会发生下面的错误
error C2065: “PCAP_SRC_IF_STRING”: 未声明的标识符
error C3861: “pcap_findalldevs_ex”: 找不到标识符
error C2065: “PCAP_OPENFLAG_PROMISCUOUS”: 未声明的标识符
error C3861: “pcap_open”: 找不到标识符

5> 或者不用添加#include "remote-ext.h".VC.NET提供的IDE环境中,可以通过执行项目菜单中的的属性进入该项目的属性配置页,通过选择配置属性树中的“C/C++预处理哭选项就增加’WPCAP’’HAVE_REMOTE’两个标号。如下图所示:


6> 如果还有问题,可以到WinPcaP官方网站上找FAQ

二、WINPCAP编程入门
利用WINPCAP捕获数据包一般要经过以下几个步骤
1、获取网络接口列表
通常, 一个基于WinPcap的应用程序所要做的第一件事, 就是获得适合的网络接口的列表.pcap_findalldevs()(或者pcap_findalldevs_ex())函数就是干这活的: 这个函数返回一个pcap_if结构的列表, 每个元素都记录了一个接口的信息. 其中, namedescription以人类可以阅读的形式, 记录了设备的信息.
2、获取设备的高级信息
WinPcap 也可以为我们提供关于接口的更多信息. pcap_findalldevs() 函数返回的 pcap_if 结构也包含了一个 pcap_addr 结构的列表, 它记录了以下信息:
1. 接口的地址列表
2. 接口的掩码列表 (与地址列表一一对应)
3. 接口的广播地址列表 (与地址列表一一对应)
4. 目标地址列表 (与地址列表一一对应)
3、打开一个接口并捕捉流量
现在我们已经知道如何获取一个接口的有关信息了, 我们可以来点真家伙了 -- 打开一个接口并捕捉流量. 接下来我们会编译一个程序, 它将捕捉网络中所有的数据包并输出他们的一些相关信息。我们使用函数 pcap_open_live() 来打开一个捕捉设备. 这里, 我们需要解释一下 snaplen, promisc to_ms 参数.
函数原型: pcap_t * pcap_open_live (char *device, int snaplen, int promisc, int to_ms, char *ebuf)
"snaplen" 参数指定了要捕捉的数据包的部分. 在某些操作系统中 (xBSD Win32), 驱动程序提供了只捕捉每个数据包其中一部分的可能性: 这样就降低了要处理的数据的量, 从而提高了捕捉程序的效率. 在例子中, 我们使用一个高出 MTU 最大值的值 (65536) 以确保可以捕捉到成个数据包.
"promisc" =1表明接口将会被设置为混杂模式. 一般情况下, 接口只处理目标地址为自己的数据; 到其他主机的数据包将会被忽略. 然而当一个接口处于混杂模式时, 它将会处理全部的流量: 也就是说, 在共享媒介, 例如非交换型以太网 (比如基于集线器的网络 ), WinPcap 可以捕捉到所有主机的数据包. 混在模式是多数捕捉程序的默认模式, 所以我们在例子中也采用这种模式.
"to_ms" 用以设置超时, 单位是毫秒. 一个从接口读取 ( Y- 捕捉) 的操作, (例如 pcap_dispatch() 或者 pcap_next_ex()), 如果没有捕捉到数据包, 那么在超过指定的时间以后就会返回. 进一步说, 如果接口处在静态模式中, to_ms 也定义了静态报告的间隔时间 (参阅 "Gathering Statistics on the network traffic " 以获取更多信息). 设置 to_ms 0, 则说明永远不会超时, 如果没有数据包到达, 那么捕捉操作将会永远不会返回, 而将其值设置为 -1 则会立刻返回.

以上取与网络中的环境配置。

事实上还有许多错误,需要解决。

如:

错误 3 error C3163: “_vsnprintf”: 属性与以前的声明不一致 d:program filesmicrosoft visual studio 9.0vcincludestdio.h 358 iflist

有人说解决办法是这个:

"VC9 CRT vsnprintf 与其他第3方定义的冲突,导致VS2008 编译错误"

error C3163: '_vsnprintf': attributes inconsistent with previous declaration

比如
wpdpackincludepcap-stdinc.h
定义了,要注释掉
//#define vsnprintf _vsnprintf




#if _MSC_VER < 1500
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#endif

但是并没有发现可以解决问题。

最后解决办法是这个:

没这么麻烦!既然PCAP.h包的stdio.h的头文件有问题,就先把stdio.h包进来。

就这样:

#include <stdio.h>
#include <pcap.h>

不是头文件有问题,只是winpcap对系统的stdio.h进行了重定议,两个版本间出现了一点小小的磨擦.

4、有时即便是按上面的方法都做了也解决不了,比如我这次就是还出现下面的问题:

错误 3 error LNK2019: 无法解析的外部符号 _pcap_loop,该符号在函数 _wmain 中被引用

……
错误 8 error LNK2019: 无法解析的外部符号 _pcap_freealldevs,该符号在函数 _wmain 中被引用

但是我用了下面的语句即可解决了:#pragma comment(lib, "wpcap.lib")

5、如果出现下面的问题:

错误 3 error LNK2019: 无法解析的外部符号 __imp__ntohs@4,该符号在函数 "void __cdecl packet_handler(unsigned char *,struct pcap_pkthdr const *,unsigned char const *)" (?packet_handler@@YAXPAEPBUpcap_pkthdr@@PBE@Z) 中被引用
用下面的语句即可解决了:#pragma comment(lib, "ws2_32.lib")

推荐阅读