Winpcap(三)

                                         打印流经网络的每个数据包信息的程序

打开网卡的功能是通过pcap_open_live()来实现的它有三个参数snaplen promisc to_ms。

snaplen用于指定所捕获包的特定部分,在一些系统上(象xBSD and Win32等)驱动只给出所捕获数据包的一部分而不是全部,这样就减少了拷贝数据的数量从而提高了包捕获的效率。promisc指明网卡处于混杂模式,在正常情况下网卡只接受去往它的包而去往其他主机的数据包则被忽略。相反当网卡处于混杂 模式时他将接收所有的流经它的数据包:这就意味着在共享介质的情况下我门可以捕获到其它主机的数据包。大部分的包捕获程序都将混杂模式设为默认,所有我们在下面的例子里也将网卡设为混杂模式。 to_ms 参数指定读数据的超时控制,超时以毫秒计算。当在超时时间内网卡上没有数据到来时对网卡的读操作将返回(如pcap_dispatch() or pcap_next_ex()等函数)。还有,如果网卡处于统计模式下(请查看“统计和收集网络数据流一节”)to_ms还定义了统计的时间间隔。如果该参数为0那么意味着没有超时控制,对网卡的读操作在没有数据到来是将永远堵塞。如果为-1那么对网卡的读操作将立即返回不管有没有数据可读。

#include "pcap.h"
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);
main()
{
  pcap_if_t *alldevs;
  pcap_if_t *d;
  int inum;
  int i=0;
  pcap_t *adhandle;
  char errbuf[PCAP_ERRBUF_SIZE]

/* 获得网卡的列表 */
  if (pcap_findalldevs(&alldevs, errbuf) == -1)
  {
    fprintf(stderr,"Error in pcap_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
        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++);
 
  /* 打开选择的网卡 */ // portion of the packet to capture. 
   // 65536 grants that the whole packet will be  captured on all the MACs. 第三个参数代表 混杂模式 ,第四个是 读超时为1秒              

if ( (adhandle= pcap_open_live(d->name, 65536, 1,  1000,  errbuf ) ) == NULL)
  {
    fprintf(stderr,"/nUnable to open the adapter. %s is not supported by WinPcap/n");

   pcap_freealldevs(alldevs);
    return -1;
  }
  printf("/nlistening on %s.../n", d->description);
  /* At this point, we don't need any more the device list. Free it */
  pcap_freealldevs(alldevs);
 
  /* 开始捕获包 */
  pcap_loop(adhandle, 0, packet_handler, NULL);
  return 0;
}


/* 对每一个到来的数据包调用该函数 */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
  struct tm *ltime;
  char timestr[16]; 
  /* 将时间戳转变为易读的标准格式*/
  ltime=localtime(&header->ts.tv_sec);
  strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
  printf("%s,%.6d len:%d/n", timestr, header->ts.tv_usec, header->len);
}

一旦网卡被打开,旧可以调用pcap_dispatch() 或pcap_loop()进行数据的捕获,这两个函数的功能十分相似不

同的是pcap_ dispatch()可以不被阻塞,而pcap_loop()在没有数据流到达时将阻塞。在这个简单的例子里用

pcap_loop()就足够了,而在一些复杂的程序里往往用pcap_dispatch().

Once the adapter is opened, the capture can be started with pcap_dispatch() or pcap_loop(). These

two functions are very similar, the difference is that pcap_ dispatch() is granted to return when

the expires while pcap_loop() doesn't return until cnt packets have been captured, so it can

block for an arbitrary period on a few utilized network. pcap_loop() is enough for the purpose of

this sample, while pcap_dispatch() is normally used in more complex program.


这两个函数都有返回的参数,一个指向某个函数(该函数用来接受数据如该程序中的packet_handler)的指针
,libpcap调用该函数对每个从网上到来的数据包进行处理和接收数据包。另一个参数是带有时间戳和包长等信
息的头部,最后一个是含有所有协议头部数据报的实际数据。注意MAC的冗余校验码一般不出现,因为当一个桢到达并被确认后网卡就把它删除了,同样需要注意的是大多数网卡会丢掉冗余码出错的数据包,所WinPcap一般不能够捕获这些出错的数据报。刚才的例子里从pcap_pkthdr中提取出了每个数据报的时间戳和长度并在显示器上打印出了他们。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值