世俱杯 2025

WinPcap初学(二)

原创|其它|编辑:郝浩|2009-08-28 10:21:13.000|阅读 895 次

概述:由于是Win32平台的开发,#ifndef WIN32...#else那段都是没用的。真正要使用到的是#include。首先声名一下,我做出来的测试程序是MFC的窗口程序。

# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>

    还是按照“winpcap使用系列” 一步步学习。先看文章里头包含的头文件。

#include "pcap.h"
#ifndef WIN32
#include 
<sys/socket.h>
#include 
<netinet/in.h>
#else
#include 
<winsock.h>
#endif

    由于是Win32平台的开发,#ifndef WIN32...#else那段都是没用的。真正要使用到的是#include<winsock.h>。首先声名一下,我做出来的测试程序是MFC的窗口程序。而MFC程序中的自动生成的stdafx.h文件中有这么一句 #include <afxwin.h// MFC 核心组件和标准组件,而在afxwin.h里头有就winsock2.h的声名。事实上winsock与winsock2是干同样活的,不过是新旧之分,所以假如你在程序中加上#include<winsock.h>的话就必然会出现函数同名的错误(winsock与winsock2很多同名的函数)。因此在我的程序中只须声名#include "pcap.h"。
    接着,看下代码。


void ifprint(pcap_if_t *d);
char *iptos(u_long in);

int main()
{
pcap_if_t 
*alldevs;
pcap_if_t 
*d;
char errbuf[PCAP_ERRBUF_SIZE+1];

/* 获得网卡的列表 */
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
  fprintf(stderr,
"Error in pcap_findalldevs: %s\n",errbuf);
  exit(
1);
}

/* 循环调用ifprint() 来显示pcap_if结构的信息*/
for(d=alldevs;d;d=d->next)
{
  ifprint(d);
}

return 1;
}

/* Print all the available information on the given interface */
void ifprint(pcap_if_t *d)
{
pcap_addr_t 
*a;

/* Name */
printf(
"%s\n",d->name);

/* Description */
if (d->description)
  printf(
"\tDescription: %s\n",d->description);

/* Loopback Address*/
printf(
"\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");

/* IP addresses */
for(a=d->addresses;a;a=a->next) {
  printf(
"\tAddress Family: #%d\n",a->addr->sa_family);

/*关于 sockaddr_in 结构请参考其他的网络编程书*/
  
switch(a->addr->sa_family)
  {
    
case AF_INET:
    printf(
"\tAddress Family Name: AF_INET\n");//打印网络地址类型
    if (a->addr)//打印IP地址
      printf("\tAddress: %s\n",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
    
if (a->netmask)//打印掩码
      printf("\tNetmask: %s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
    
if (a->broadaddr)//打印广播地址
      printf("\tBroadcast Address: %s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
    
if (a->dstaddr)//目的地址
      printf("\tDestination Address: %s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
    
break;
    
default:
    printf(
"\tAddress Family Name: Unknown\n");
    
break;
  }
}
printf(
"\n");
}

/* 将一个unsigned long 型的IP转换为字符串类型的IP */
#define IPTOSBUFFERS   12
char *iptos(u_long in)
{
  
static char output[IPTOSBUFFERS][3*4+3+1];
  
static short which;
  u_char 
*p;

  p 
= (u_char *)&in;
  which 
= (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
  sprintf(output[which], 
"%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
  
return output[which];
}


    这些使用到一些控制台程序的函数,不过对于MFC程序没有大碍。先不说ifprint和iptos的作用,我们来看来pcap_if_t这个结构。
     在pcap.h中它有一个另名pcap_if,至于为什么要改名字我也不太清楚。(为了说明这个一个type?)在官方的文档中(...\WpdPack\docs\html\structpcap__if.html)对pcap_if进行如下定义:

  if not NULL, a pointer to the next element in the list; NULL for the last element of the list
char * 
  a pointer to a string giving a name for the device to pass to
char * 
  if not NULL, a pointer to a string giving a human-readable description of the device
  a pointer to the first element of a list of addresses for the interface
u_int 
  PCAP_IF_ interface flags. Currently the only possible flag is PCAP_IF_LOOPBACK, that is set if the interface is a loopback interface.


     next是对下一个设备驱动的指针,name是本驱动的名字(基本上是一些不知所云的数字),description是驱动的描述(如Realtek RTL8169/8110 Family Gigabit Ethernet NIC,这个程序员就比较清楚了),pcap_addr则是另一个pcap.h中定义的结构,最后的flags目前为0。 官方文档对pcap_addr定义如下:

  if not NULL, a pointer to the next element in the list; NULL for the last element of the list
sockaddr * 
  a pointer to a struct sockaddr containing an address
sockaddr * 
  if not NULL, a pointer to a struct sockaddr that contains the netmask corresponding to the address pointed to by addr.
sockaddr * 
  if not NULL, a pointer to a struct sockaddr that contains the broadcast address corre­ sponding to the address pointed to by addr; may be null if the interface doesn't support broadcasts
sockaddr * 
  if not NULL, a pointer to a struct sockaddr that contains the destination address corre­ sponding to the address pointed to by addr; may be null if the interface isn't a point- to-point interface

    其中,addr为IP地址,netmask为子网掩码(以上两个都为平时常用的网络连接设置),broadaddr为广播地址(说明参照百度百科),dstaddr为目标地址(具体使用不太清楚,什么叫点对点接口?什么情况下会有这个接口?哪位高人给我指点一下!)。以上4部分都是sockaddr这个结构,它的定义在ws2def.h中。


//
// Structure used to store most addresses.
//
typedef struct sockaddr {

#if (_WIN32_WINNT < 0x0600)
    u_short sa_family;
#else 
     ADDRESS_FAMILY sa_family;           
// Address family.
#endif //(_WIN32_WINNT < 0x0600)

    CHAR sa_data[
14];                   // Up to 14 bytes of direct address.
} SOCKADDR, *PSOCKADDR, FAR *LPSOCKADDR;


    上面的0x0600是vista的版本号,就是说当系统为XP或以下的时候用u_short的定义(其实ADDRESS_FAMILY也就是个ushort,只是换个名字)。还是回来看下它的结构,主要是后面的sa_data[14],这个参考,里面说得很详细。下面是截图,可以很清楚地看到前2个字节都是0,接下来的4个是有值的,后面的都是0。
    实际上那4个有值的字节就是32位的地址,如192.168.0.1等。
    现在让我们回来看那两个函数ifprint及iptos。在看完pcap_if_t等结构的说明后,想必你也看出来ifprint就是对pcap_if_t结构的解析,iptos就是对sockaddr的解析了吧。
     目前为止还没有自己写的东西,谁叫我还是个新手,一步步学吧。下一步是做一个可以测试在1000M网卡下WinPcap发送能力的极限能到多少的小程序,以前100M的话好像只能到60M。


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@dpuzeg.cn

文章转载自:博客园

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP