在libpcap中丢失-如何使用setnonblock()/我应该使用pcap\u dispatch()还是pcap\u next\u ex()来实现实时性?

在libpcap中丢失-如何使用setnonblock()/我应该使用pcap\u dispatch()还是pcap\u next\u ex()来实现实时性?,c,multithreading,freebsd,libpcap,C,Multithreading,Freebsd,Libpcap,我正在构建一个网络嗅探器,它将在PFSense上运行,用于监视IPSecVPN。我是在FreeBSD8.4下编译的 我选择使用C中的libpcap作为包捕获引擎,使用Redis作为存储系统。 每秒将有数百个数据包需要处理,系统将全天运行 目标是有一个显示网络活动图表的网页,如果可能的话,每分钟或几秒钟更新一次。 当我的嗅探器捕获一个数据包时,它将确定它的大小、谁(在我们的VPN上下文中是一个地理位置的站点)将它发送给谁以及何时发送给谁。然后这些信息需要存储在数据库中 我做了很多研究,但是我对li

我正在构建一个网络嗅探器,它将在PFSense上运行,用于监视IPSecVPN。我是在FreeBSD8.4下编译的

我选择使用C中的libpcap作为包捕获引擎,使用Redis作为存储系统。 每秒将有数百个数据包需要处理,系统将全天运行

目标是有一个显示网络活动图表的网页,如果可能的话,每分钟或几秒钟更新一次。 当我的嗅探器捕获一个数据包时,它将确定它的大小、谁(在我们的VPN上下文中是一个地理位置的站点)将它发送给谁以及何时发送给谁。然后这些信息需要存储在数据库中

我做了很多研究,但是我对libpcap有点迷茫,特别是我应该如何捕获数据包

1) 我应该使用什么函数来检索数据包?pcap_环?pcap_调度?还是下一个pcap?根据我在网上读到的内容,循环和调度正在阻止执行,所以pcap_next_ex似乎是解决方案

2) 我们应该什么时候使用pcap_setnonblock?我的意思是使用哪种捕获功能?pcap_环?所以如果我使用pcap_循环,执行不会被阻止

3) 多线程是实现这一点的方法吗?一个线程一直在运行捕获数据包、分析数据包并将一些数据存储在一个数组中,第二个线程每分钟启动一次,清空这个数组

我想得越多,我就越迷路,所以如果我不清楚,请原谅,不要犹豫,向我询问准确度

欢迎任何帮助

编辑:

我目前正在尝试实现一个工作池,回调函数只在作业队列中放置一个新作业。欢迎任何帮助。稍后我会发布更多细节

1) 我应该使用什么函数来检索数据包?pcap_环?pcap_调度?还是下一个pcap?根据我在网上读到的内容,循环和调度正在阻止执行,所以pcap_next_ex似乎是解决方案

如果没有数据包就绪,并且您没有将
pcap\u t
置于非阻塞模式,则所有这些函数都会阻塞等待数据包

pcap\u loop()
包含一个无限期运行的循环(或者直到调用
pcap\u breakloop()
并发生错误,或者,如果指定了计数,则计数将耗尽)。因此,它可能会等待不止一次

pcap\u dispatch()
阻止等待一批数据包到达,如果没有可用的数据包,则循环处理该批数据,然后返回,因此它最多只等待一次

pcap\u next()
pcap\u next\u ex()
等待数据包可用,然后返回它

2) 我们应该什么时候使用pcap_setnonblock?我的意思是使用哪种捕获功能?pcap_环?所以如果我使用pcap_循环,执行不会被阻止

不,不会,但这意味着对
pcap\u loop()
的调用可能会在不处理任何数据包的情况下返回;您必须再次调用它来处理稍后到达的任何数据包。非阻塞和
pcap\u loop();您最好使用
pcap\u dispatch()
pcap\u next\u ex()

3) 多线程是实现这一点的方法吗?一个线程一直在运行捕获数据包、分析数据包并将一些数据存储在一个数组中,第二个线程每分钟启动一次,清空这个数组

(该数组可能是一个队列,第一个线程将数据包附加到队列的末尾,第二个线程从队列的头部移除数据包并将其放入数据库。)

这将是一种可能性,尽管我不确定它是否应该基于计时器。考虑到许多数据包捕获机制(包括*BSD和OS X使用的BPF)都是成批交付数据包的,也许您应该有一个类似于

for (;;) {
    pcap_dispatch(p, -1, callback);
    wake up dumper thread;
}
(这很简单-您可能希望检查
pcap\u dispatch()
返回值中的错误)

回调将把传递给它的数据包添加到队列的末尾

转储程序线程将从队列头提取数据包,并将它们添加到数据库中

这不要求pcap不阻塞。在单CPU核心机器上,它依赖于调度程序对线程进行时间切片

我目前正在尝试实现一个工作池,回调函数只在作业队列中放置一个新作业


请注意,回调函数返回后,其第二个参数指向的
const struct pcap_pkthdr
结构和第三个参数指向的原始数据包数据都无效,因此如果要在作业中处理它们,您必须复制它们,包括您将在该作业中处理的所有数据包数据的副本。您可能想考虑回调例程中的一些处理,即使它只计算需要保存什么包数据(例如IP源和目的地址),并且复制它,因为这可能比复制整个包要便宜。

谢谢您的时间!我现在不再从事这个项目,但当我重新打开这个案例时,你的解释肯定会非常有用。