• 【VS开发】使用WinPcap编程(2)——打开网络设备并且开始捕获数据包


    这里需要特别强调的一个数据结构是pcap_t,它相当于一个文件描述符,代表一个已经打开的设备。我们对这个设备进行操作,就是对这个文件描述符进行操作。

     

          首先是打开一个已知的设备,使用pcap_open()这个函数,其原型如下:

    pcap_t * pcap_open (const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf)


          1、source是我们所要打开的设备。当我们获取所有的设备之后,这个source就是d->name。如果是文件的话,就是文件的名字,也是d->name。

          2、snaplen是我们抓取的数据包的大小,100就是抓取整个数据包的前100bytes,65536最大,把整个包都包括了。不过有时候不管用(看设备)。

          3、flags是设置网络设备打开的状态的,最重要的是PCAP_OPENFLAG_PROMISCUOUS,表示这个网络设备以混杂模式打开,可以捕捉局域网中所有数据包。

          4、read_timeout是设置延迟时间(milliseconds)用的。捕捉数据包的时候,延迟一定的时间,然后再调用内核中的程序,这样效率较高。0表示没有延迟,没有包到达的时候永不返回。-1表示立即返回。

          5、auth是远程机器的登录信息。本地机器则为NULL。

          6、errbuf存储出错信息。

          return: 返回这个打开设备的描述符,如果出错,返回NULL。

     

          打开设备之后就要开始捕捉数据包了。pcap_loop()函数对捕捉到的数据包进行处理,每次处理一个数据包。其函数原型如下:

    int pcap_loop (pcap_t *p, int cnt, pcap_handler callback, u_char *user)

          1、p就是我们打开的某个网络设备的描述符。

          2、cnt是count,表示这个循环会总共处理多少个数据包。比如30,就是处理30个数据包。0表示没有限定。

          3、callback是一个函数指针,用来具体操作如何对数据包进行处理。

          4、user是用户信息。我也不知道怎么用,一般为NULL。

     

          下面说一下上面函数中的函数指针,用来具体操作处理数据包。其定义如下:

    typedef void(* pcap_handler )(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)

          1、user就是pcap_loop()函数中的user,一般也没什么用,在函数内部都用(VOID)user; 进行标记。

          2、pkt_header是捕捉到这个数据包时WinPcap添加的一些信息,有时间戳、捕捉到的包长度、实际包长度这些信息。参看这里

          3、pkt_data就是实际的数据包了,包括ethernet header, ip header, tcp header, real data等等各种不同的信息。

     

          附上一个源代码:

    #define _CRT_SECURE_NO_WARNINGS
    
    #include "pcap.h"
    
    void packet_handler(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);
    
    int main()
    {
    	pcap_t *cap_ins_des;	// descriptor of an opened capture instance
    	pcap_if_t *alldevs;		// pcap_if_t is interface type
    	pcap_if_t *d;
    	char errbuf[PCAP_ERRBUF_SIZE];	// store error information
    	int i;
    	//char source[PCAP_BUF_SIZE];
    
    	/* find all useful devices in my local host */
    	if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) {
    		printf("%s
    ", errbuf);
    		exit(-1);
    	}
    
    	/* choose one interface */
    	d = alldevs;
    	while (d != NULL) {
    		printf("%s
    ", d->description == NULL ? NULL : d->description);
    		d = d->next;
    	}
    	d = alldevs;
    	scanf("%d", &i);
    	while (i--)
    		d = d->next;
    
    	/* open this interface */
    	cap_ins_des = pcap_open(d->name /* char *source */, 100, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf);
    	if (cap_ins_des == NULL) {
    		printf("%s
    ", errbuf);
    		exit(-1);
    	}
    
    	/* free all the devices, because we don't use them any more */
    	pcap_freealldevs(alldevs);
    
    	/* start the capture, deal with one packet each loop */
    	pcap_loop(cap_ins_des, 30 /* capture 30 packets */, packet_handler, NULL);
    
    	return 0;
    }
    
    void packet_handler(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
    {
    	time_t time = pkt_header->ts.tv_sec;
    	struct tm *ltime = localtime(&time);
    	char timestr[16];
    
    	(VOID)user;
    	(VOID)pkt_data;
    
    	strftime(timestr, sizeof timestr, "%H:%M:%S", ltime);
    
    	printf("%s. %d, %d, %d
    ", timestr, pkt_header->ts.tv_usec, pkt_header->caplen, pkt_header->len);
    }
  • 相关阅读:
    epoll的LT和ET(转)
    js和jQuery的互相转换
    Spring的回滚问题
    Spring的事务
    分布式锁的实现方式
    xml是什么
    ajax的4个字母分别是什么意思
    try、catch、finally都有return语句时执行哪个
    静态变量、实例变量、局部变量线程安全吗,为什么
    String和StringBuilder、StringBuffer的区别
  • 原文地址:https://www.cnblogs.com/huty/p/8518341.html
Copyright © 2020-2023  润新知