WinPcap编程渐进教程2008-09-2516:59:51标签:WinPcap编程教程[推送到技术圈]【网络编程】[翻译]WinPcap编程渐进教程(1)--[翻译]WinPcap编程渐进教程WinPcap教程原文出处:作者:LorisDegioanni(degioanni@polito.it),NetGroup,PolitecnicodiTorino译者:记忆碎片(val_cong@htomail.com)概述:这篇教程将会指引读者逐步了解WinPcap编程,从简单的基础函数(获取网络接口列表,捕捉数据包)到更高级的内容(处理发送队列,网络流量统计).教程中包括一些代码片断,以及一些简单但完整的例子,读者可以参考这些例子更好的理解教程的内容.这些例子全部用C语言写成,所以基本的C语言编程知识是必要.同时,因为这篇教程的内容是与底层网络紧密相连的,所以笔者假设读者已经具备有关网络和协议的相关知识.译者的话:WinPcap是一套免费的,基于Windows的网络接口API,它在底层网络操作方面对程序员很有帮助.这篇文档翻译自WinPcapDocumentation3.0中的WinPcaptutorial:astepbystepguidetoprogramWinPcap一部分.这篇教程对初学者的帮助很大,尤其是简短清晰的例子,但这篇教程只是整个文档的一小部分,我认为你仍然需要参考文档的其它部分来了解各种结构等信息.教程中注有前缀Y-的部分是译者为了让读者更明白作者的意思添加的,原文中没有.1.获取网络接口列表通常,一个基于WinPcap的应用程序所要做的第一件事,就是获得适合的网络接口的列表.Libpcap中的pcap_findalldevs()函数就是干这活的:这个函数然回一个pcap_if结构的列表,每个元素都记录了一个接口的信息.其中,name和description以人类可以阅读的形式,记录了设备的信息.下面的源代码输出可用的网络接口的列表,并且在没有找到任何借口的情况下输出错误信息:代码#includepcap.hmain(){pcap_if_t*alldevs;pcap_if_t*d;inti=0;charerrbuf[PCAP_ERRBUF_SIZE];/*取得列表*/if(pcap_findalldevs(&alldevs,errbuf)==-1){fprintf(stderr,Errorinpcap_findalldevs:%s\n,errbuf);exit(1);}/*输出列表*/for(d=alldevs;d;d=d-next){printf(%d.%s,++i,d-name);if(d-description)printf((%s)\n,d-description);else/*Y-没有有效的描述*/printf((Nodescriptionavailable)\n);}if(i==0){/*Y-没有有效的接口,可能是因为没有安装WinPcap*/printf(\nNointerfacesfound!MakesureWinPcapisinstalled.\n);return;}我们来看看这段代码.首先,和其他的libpcap函数一样,pcap_findalldevs(),有一个错误缓冲区(errbuf)参数.这个参数是一个字符串指针,一旦发生错误,libpcap将会在这里填入错误描述.然后,请注意,pcap_findalldev系统下的s()函数同时也被UNIX下的libpcap所支持,但是并不是所有的操作系统都支持“网络接口描述”(description)这一项.所以,如果我们想写一个可以移植的的应用程序,那么我们必须要为描述为“空”(null)的情况做好准备:遇到这种情况我们就输出一个“没有有效的描述”的消息.最后我们通过pcap_freealldevs()函数来释放接口列表.现在让我们编译并运行我们的第一个WinPcap程序.如果你使用UNIX或者Cgywin的话,你只需要以下命令:gcc-otestaprogtestprog.c-lpcap在Windows环境中(Y-如果你使用MicrosoftVisualC++),你需要建立一个工程,按照UsingWinPcapinyourprograms一节中说明来做.不过,我仍然建议你参照Winpcap开发者包(WinPcapdeveloper'spack)中的例子,那些例子包括了所以配置完善的工程,以及全部你所需要的库和包含文件.(Y-你可以在本章最后找到MicrosoftVisualC++的配置方法)假设现在你已经成功编译了程序,我们就来运行它.在我的WinXP工作站上,输出结果是:1.{4E273621-5161-46C8-895A-48D0E52A0B83}(RealtekRTL8029(AS)EthernetAdapter)2.{5D24AE04-C486-4A96-83FB-8B5EC6C7F430}(3ComEtherLinkPCI)就如你所看到的,网络接口的名称(当打开这个接口时,需要传递这个名称给libpcap库)在windows环境下几乎是没有办法读懂的(Y-严重同意),所以输出一个描述对于你的用户来说是非常有帮助的.附注:MicrosoftVisualC++工程的设置1.下载并安装WinPcap,推荐的版本是3.02.从并解压缩/*我们不再需要列表了,释放*/pcap_freealldevs(alldevs);}3.用MicrosoftVisualC++建立一个空工程(emptyproject)4.复制源代码5.把WinpcapDeveloper'sPack中的Includes目录添加为新的包含文件目录6.添加库wpcap.lib和wsock32.lib一路达计数器提示:统计网站设置不对统计网站:应为luluww.blogchina.com现在修改【网络编程】[翻译]WinPcap编程渐进教程(2)--原文出处:作者:LorisDegioanni(degioanni@polito.it),NetGroup,PolitecnicodiTorino译者:记忆碎片(val_cong@htomail.com)获取设备的高级信息上一课我们介绍了如何获取一个设备的基本信息(比如设备名称和设备描述).实际上,WinPcap也可以为我们提供关于接口的更多信息.由pcap_findalldevs()函数返回的pcap_if结构也包含了一个pcap_addr结构的列表,它记录了以下信息:1.接口的地址列表2.接口的掩码列表(与地址列表一一对应)3.接口的广播地址列表(与地址列表一一对应)4.目标地址列表(与地址列表一一对应)下面例子中的ifprint()函数将会输出pcap_if结构的全部内容.它包括了pcap_findalldevs()函数所返回的所有元素.(Y-全部有效接口)代码/**Copyright(c)1999-2002*PolitecnicodiTorino.Allrightsreserved.**Redistributionanduseinsourceandbinaryforms,withorwithout*modification,arepermittedprovidedthat:(1)sourcecodedistributions*retaintheabovecopyrightnoticeandthisparagraphinitsentirety,(2)*distributionsincludingbinarycodeincludetheabovecopyrightnoticeand*thisparagraphinitsentiretyinthedocumentationorothermaterials*providedwiththedistribution,and(3)alladvertisingmaterialsmentioning*featuresoruseofthissoftwaredisplaythefollowingacknowledgement:*``ThisproductincludessoftwaredevelopedbythePolitecnico*diTorino,anditscontributors.''Neitherthenameof*theUniversitynorthenamesofitscontributorsmaybeusedtoendorse*orpromoteproductsderivedfromthissoftwarewithoutspecificprior*writtenpermission.*THISSOFTWAREISPROVIDED``ASIS''ANDWITHOUTANYEXPRESSORIMPLIED*WARRANTIES,INCLUDING,WITHOUTLIMITATION,THEIMPLIEDWARRANTIESOF*MERCHANTABILITYANDFITNESSFORAPARTICULARPURPOSE.*/#includepcap.h#ifndefWIN32#include#include#else#include#endifvoidifprint(pcap_if_t*d);char*iptos(u_longin);intmain(){pcap_if_t*alldevs;pcap_if_t*d;charerrbuf[PCAP_ERRBUF_SIZE+1];/*获得设备列表*/if(pcap_findalldevs(&alldevs,errbuf)==-1){fprintf(stderr,Errorinpcap_findalldevs:%s\n,errbuf);exit(1);}/*遍历所有元素*/for(d=alldevs;d;d=d-next){ifprint(d);}return1;}/*Printalltheavailableinformationonthegiveninterface*/voidifprint(pcap_if_t*d){pcap_addr_t*a;/*名称*/printf(%s\n,d-name);/*描述*/if(d-description)printf(\tDescription:%s\n,d-description);/*回环地址*/printf(\tLoopback:%s\n,(d-flags&PCAP_IF_LOOPBACK)?yes:no);/*IP地址*/for(a=d-addresses;a;a=a-next){printf(\tAddressFamily:#%d\n,a-addr-sa_family);switch(a-addr-sa_family){caseAF_INET:printf(\tAddressFamilyName:AF_INET\n);if(a-addr)/*Y-IP地址*/printf(\tAddress:%s\n,iptos(((structsockaddr_in*)a-addr)-sin_addr.s_addr));if(a-netmask)/*Y-掩码*/printf(\tNetmask:%s\n,iptos(((structsockaddr_in*)a-netmask)-sin_addr.s