5
// Open the ethernet adapter
handle = pcap_open_live("eth0", 65356, 1, 0, errbuf);

// Make sure it opens correctly
if(handle == NULL)
{
    printf("Couldn't open device : %s\n", errbuf);
    exit(1);
}

// Compile filter
if(pcap_compile(handle, &bpf, "udp", 0, PCAP_NETMASK_UNKNOWN))
{
    printf("pcap_compile(): %s\n", pcap_geterr(handle));
    exit(1);
}

// Set Filter
if(pcap_setfilter(handle, &bpf) < 0)
{
    printf("pcap_setfilter(): %s\n", pcap_geterr(handle));
    exit(1);
}

// Set signals
signal(SIGINT, bailout);
signal(SIGTERM, bailout);
signal(SIGQUIT, bailout);

// Setup callback to process the packet
pcap_loop(handle, -1, process_packet, NULL);

process_packet 函数去掉了 header 并对数据进行了一些处理。但是,当它花费太长时间时,我认为它正在丢弃数据包。

如何使用 pcap 侦听 udp 数据包并能够对数据进行一些处理而不会丢失数据包?

4

1 回答 1

3

好吧,您没有无限的存储空间,因此,如果您的运行速度持续低于数据包到达的速度,您在某些时候丢失数据。

当然,如果你有足够的存储空间,并且平均而言,你不会落后(例如,你可能在爆发时跑得很慢,但有一些安静的时间你可以赶上),那将缓解这个问题。

一些网络嗅探器会这样做,只需将原始数据写入文件以供以后分析。

这是一个你也可以使用的技巧,但不一定适用于文件。可以使用像循环缓冲区这样的大型内存结构,其中一个线程(捕获线程)写入原始数据,另一个线程(分析)读取和解释。而且,因为每个线程只处理缓冲区的一端,您甚至可以在没有锁(或非常短的锁)的情况下构建它。

这也可以很容易地检测您是否已经用完缓冲区并引发某种错误,而不仅仅是在应用程序级别丢失数据。

当然,这一切都取决于您的“尽可能简单和快速”的捕获线程能够跟上流量。


澄清我的意思,修改你的process_packet函数,使它除了将原始数据包写入一个巨大的循环缓冲区(检测溢出并采取相应措施)之外什么都不做。这应该使它尽可能快,避免 pcap 本身丢弃数据包。

然后,有一个分析线程从队列中取出东西并完成以前完成的工作process_packet(“摆脱标题并对数据进行一些处理”位)。


另一种可能的解决方案是增加 pcap 内部缓冲区大小。根据手册页:

为捕获而到达的数据包存储在缓冲区中,因此应用程序不必在它们到达后立即读取它们。

在某些平台上,可以设置缓冲区的大小;尺寸太小可能意味着,如果捕获的数据包太多并且快照长度不限制缓冲的数据量,如果缓冲区在应用程序可以从中读取数据包之前填满,数据包可能会被丢弃,而太大的大小可能会使用比防止数据包丢失所需的更多的不可分页操作系统内存。

缓冲区大小用 设置pcap_set_buffer_size()


想到的唯一另一种可能性是确保您对每个数据包所做的处理尽可能优化。

将处理拆分为收集和分析应该可以缓解跟不上的问题,但仍然需要安静的时间才能赶上。如果您的网络流量始终超出您的分析可以处理的范围,那么您所做的只是延迟问题。优化分析可能是保证您永远不会丢失数据的唯一方法。

于 2013-08-29T02:17:13.057 回答