这一次要分析的实例程序跟上一讲非常类似(“打开适配器并捕获数据包”),略微不同的一点是本次将pcap_loop()函数替换成了pcap_next_ex()函数。本节的重点也就是说一下这两个函数之间的差异。我们知道pcap_loop()函数是基于回调的原理来进行数据捕获的,如技术文档所说,这是一种精妙的方法,并且在某些场合下,它是一种很好的选择。但是在处理回调有时候会并不实用,它会增加程序的复杂度,特别是在多线程的C++程序中。而对于pcap_next_ex()函数而言,可以通过直接调用它来获得一个数据包,也只有在调用了这个函数才能收到数据包。pcap_next_ex()函数跟pcap_loop()的回调函数参数是相同的:

int pcap_next_ex  ( pcap_t *  p,  
struct pcap_pkthdr ** pkt_header,
const u_char ** pkt_data
)

第一个参数是网络适配器的描述符;第二个参数是一个指向pcap_pkthdr结构体的指针;第三个参数是指向数据报数据的缓冲的指针。

来看一下实例程序的代码:

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include "pcap.h" typedef struct sockaddr_in sockad;
/* 从tcptraceroute数字IP地址转换为字符串 */
#define IPTOSBUFFERS 12
char *iptos(u_long in)
{
static char output[IPTOSBUFFERS][*++];
static short which;
u_char *p; p = (u_char *)&in;
which = (which + == IPTOSBUFFERS ? : which + );
sprintf(output[which], "%d.%d.%d.%d", p[], p[], p[], p[]);
return output[which];
} void ifprint(pcap_if_t *d,int* i)
{
pcap_addr_t *a; printf("%d. %s", ++(*i), d->name);
if (d->description)
printf(" (%s)\n", d->description);
else
printf(" (No description available)\n");
for(a=d->addresses;a;a=a->next)
{
switch(a->addr->sa_family)
{
case AF_INET:
if(a->addr)
printf("\tIPv4地址:%s\n",iptos(((sockad *)a->addr)->sin_addr.s_addr));
break;
}
}
} int main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int inum;
int i=;
pcap_t *adhandle;
int res;
char errbuf[PCAP_ERRBUF_SIZE];
struct tm *ltime;
char timestr[];
struct pcap_pkthdr *header;
u_char *pkt_data; /* 获取设备列表 */
if (pcap_findalldevs(&alldevs, errbuf) == -)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit();
} /* 打印列表 */
for(d=alldevs; d; d=d->next)
{
ifprint(d,&i);
} if(i==)
{
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
return -;
} printf("Enter the interface number (1-%d):",i);
scanf("%d", &inum); if(inum < || inum > i)
{
printf("\nInterface number out of range.\n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -;
} /* 跳转到选定的适配器 */
for(d=alldevs, i=; i< inum- ;d=d->next, i++); /* Open the adapter */
if ( (adhandle= pcap_open_live(d->name, // name of the device
, // portion of the packet to capture.
// 65536 grants that the whole packet will be captured on all the MACs.
, // promiscuous mode
, // read timeout
errbuf // error buffer
) ) == NULL)
{
fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -;
} printf("\nlistening on %s...\n", d->description); /* At this point, we don't need any more the device list. Free it */
pcap_freealldevs(alldevs); /* 检索包 */
while((res = pcap_next_ex( adhandle, &header, &pkt_data)) >= ){ if(res == )
// Timeout elapsed
continue; //convert the timestamp to readable format
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);
} if(res == -){
printf("Error reading the packets: %s\n", pcap_geterr(adhandle));
return -;
} return ;
}

文档上在最后简单地比较了一下pcap_next_ex()函数和pcap_next()函数的区别,通过函数名我们知道pcap_next_ex()函数是在pcap_next()基础上扩展得到的。为什么会扩展?根据文档说明可以知道,pcap_next()函数有一些缺陷。比如它效率很低,尽管隐藏了回调的方式,但它仍然依赖于函数pcap_dispatch();另外,它不能检测到EOF这个状态,那么如果数据包是从文件中读取过来的,那么它就不那么好用了。显然,pcap_next_ex()函数在此基础上做出了一些改进。最后我们来看一下pcap_next_ex()函数的返回值,引用文档中的描述:

The return value can be:

  • 1 if the packet has been read without problems (数据读取无误)
  • 0 if the timeout set with pcap_open_live() has elapsed. In this case pkt_header and pkt_data don't point to a valid packet
  • (pcap_open_live()设置的超时时间超时,在这种情况下pkt_header和pkt_data指向一个非法的数据)
  • -1 if an error occurred (出错)
  • -2 if EOF was reached reading from an offline capture (读取到EOF,应该是文件)

winPcap编程之不用回调方法捕获数据包(五 转)的更多相关文章

  1. winPcap_6_不用回调方法捕获数据包

    用 pcap_next_ex() 函数代替 _5_ 中的 pcap_loop()函数: pcap_loop()函数是基于回调的原理来进行数据捕获,这是一种精妙的方法,并且在某些场合中,它是一种很好的选 ...

  2. Winpcap笔记4之不用回调函数捕获数据包

    函数1: pcap_next_ex(pcap_t*                       p, struct pcap_pkthdr**   pkt_header, const u_char*  ...

  3. winPcap编程之打开适配器并捕获数据包(四 转)

    在贴源码之前先介绍一个将要用到的很重要的函数--pcap_open(),下面是pcap_open()在remote-ex.h中的声明: pcap_t *pcap_open(const char *so ...

  4. 【VS开发】使用WinPcap编程(4)——把网络数据包存储到一个文件中

    这里用到的数据结构是pcap_dumper_t,这也是一个相当于文件描述符的东西,我们在用的时候先指定pcap_dumper_t *dumpfp; 使用两个函数来存储网络数据,一个是pcap_dump ...

  5. Winpcap笔记3之打开适配器并捕获数据包

    上一讲中知道了如何获取适配的信息,这一将我们讲写一个程序蒋每一个通过适配器的数据包打印出来. 打开设备的函数是pcap_open().函数原型是 pcap_t* pcap_open(const cha ...

  6. winPcap_5_打开适配器并捕获数据包

    知道如何获取适配器的信息了,那我们就开始一项更具意义的工作,打开适配器并捕获数据包.编写一个程序,将每一个通过适配器的数据包打印出来. 打开设备的函数是 pcap_open(). (Open a ge ...

  7. winpcap使用之捕获数据包

    第一种方法,调用回调函数 #include "pcap.h" /* packet handler 函数原型 */ void packet_handler(u_char *param ...

  8. Python3+pyshark捕获数据包并保存为文件

    一.直接使用wireshark捕获数据包并保存为文件 可以使用wireshark通过图形界面的操作来实现捕获数据包并保存为文件. wireshark默认捕获的数据包保存为临时文件,如果最后退出时不选择 ...

  9. Linux系统捕获数据包流程

    Linux系统捕获数据包流程 为了提高数据包的捕获效率,瓶颈问题是一个需要非常关注的焦点.减少在捕获数据包过程中的瓶颈,就能够提高数据包捕获的整体性能.下面本文将以Linux操作系统为平台,分析捕获数 ...

随机推荐

  1. Spring Ioc DI 原理

    IOC(DI):其实这个Spring架构核心的概念没有这么复杂,更不像有些书上描述的那样晦涩.Java程序员都知道:java程序中的每个业务逻辑至少需要两个或以上的对象来协作完成,通常,每个对象在使用 ...

  2. 结对编程1----基于java的四则运算生成器

    小组成员:王震(201421123054).王杰(201421123055) Coding地址:https://git.coding.net/a506504661/sssss.git 一.题目描述 我 ...

  3. Sudoku Generator

    Sudoku 算法 标签(空格分隔): 软工实践 设想:通过第一行,来生成2, 3行的排列,再通过1 - 3 生成4 - 6排列. 2 3 行的生成由上一行生成 公式为$grid[i][j] = gr ...

  4. 201521123063 《Java程序设计》 第4周学习总结

    1.本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. 类设计 一般在设计类的时候,要考虑这些类是否有共性,还要考虑其独特性,使共同的父类拥有这些共性 ...

  5. 201521123104《Java程序设计》第4周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. (1)继承时子类将获得父类的属性与方法,并具有自身特有的属性与方法. (2)使用super还 ...

  6. 201521123096《Java程序设计》第四周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. 继承能够动态绑定,运行时能够自动的选择调用方法,十分方便. 2. 书面作业 (1)注释的应用 ...

  7. 201521123086《JAVA程序设计》第二周学习总结

    一.本章学习总结 学会在Java程序中使用函数,使程序层次更清晰 使用StringBuilder编写代码,减少内存空间的占用 使用BigDecimal精确计算浮点数 使用枚举类型编写函数,掌握返回值使 ...

  8. 201521123025《java程序设计》第11周学习总结

    1. 本周学习总结 2. 书面作业 Q1.互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) 1.1 除了使用synchronized修饰方法实现互斥同步访问,还有什么办法实现互斥同步 ...

  9. 201521123018 《Java程序设计》第13周学习总结

    1. 本章学习总结 2. 书面作业 一.1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同? 返回时间 ...

  10. linux c函数指针的应用

    头文件:1.h #include<stdio.h> int nul_func(); int test1(int a,int b); int test2(int a,int b,int c) ...