7.1.3 打开与关闭网络适配器的实例

在下面实例程序中会打开一个网络适配器并捕获相应的数据包,该程序会把通过该适配器的每个数据包的长度打印出来,同时打印每个数据包的捕获时间,完整的代码见[ch7/openadapter工程]。


defne WIN32

defne HAVE_REMOTE

include<stdio.h>

include"pcap.h"

include<winsock.h>

/捕获数据包的回调函数的原型/

void packet_handler(u_char*param,

const struct pcap_pkthdrheader,const u_charpkt_data);

int main()

{

pcap_if_t*alldevs;

pcap_if_t*d;

int inum;

int i=0;

pcap_t*adhandle;

char errbuf[PCAP_ERRBUF_SIZE];

/获取本机的网络设备列表/

if(pcap_fndalldevs_ex(PCAP_SRC_IF_STRING,NULL,

&alldevs,errbuf)==-1)

{

fprintf(stderr,

"Error in pcap_fndalldevs:%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

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");

/释放设备列表/

pcap_freealldevs(alldevs);

return-1;

}

/跳转到选中的适配器/

for(d=alldevs,i=0;i<inum-1;d=d->next,i++);

/打开设备/

if((adhandle=pcap_open(

d->name,//设备名

65536,//保证捕获到数据链路层上每个数据包的全部内容

PCAP_OPENFLAG_PROMISCUOUS,//混杂模式

1000,//读取超时时间

NULL,//远程机器验证

errbuf//错误缓冲池

))==NULL)

{

fprintf(stderr,"\nUnable to open the adapter.

%s is not supported by WinPcap\n",d->name);

/释放设备列表/

pcap_freealldevs(alldevs);

return-1;

}

/在选中的设备接口上监听数据/

printf("\nlistening on%s…\n",d->description);

/释放设备列表/

pcap_freealldevs(alldevs);

/开始捕获/

pcap_loop(adhandle,0,packet_handler,NULL);

/关闭设备/

pcap_close(adhandle);

return 0;

}

/每次捕获到数据包时,都会自动调用该回调函数/

void packet_handler(u_char*param,

const struct pcap_pkthdrheader,const u_charpkt_data)

{

struct tm*ltime;

char timestr[16];

time_t local_tv_sec;

/将时间戳转换成可识别的格式,header->ts存储了数据包被捕获的时间/

local_tv_sec=header->ts.tv_sec;

ltime=localtime(&local_tv_sec);

strftime(timestr,sizeof timestr,"%H:%M:%S",ltime);

/打印数据包的捕获时间与数据包的长度/

printf("%s,%.6d len:%d\n",

timestr,header->ts.tv_usec,header->len);

}


在本实例中,将pcap_open函数的snaplen参数值设定为65535,这个值比能遇到的最大的网络最大传输单元MTU(Maximum Transfer Unit)还要大,同时这里还使用了混杂模式,这样,可确保总能收到完整的数据包。实例程序的运行结果如图7-1与图7-2所示。

7.1.3 打开与关闭网络适配器的实例 - 图1

图 7-1 选择网络设备接口(此处选择2)

7.1.3 打开与关闭网络适配器的实例 - 图2

图 7-2 打印数据包的捕获时间与长度