// 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函数摆脱了标题并对数据进行了一些处理。但是,当它花费太长时间时,我认为它正在丢弃数据包。
如何使用pcap监听udp数据包并能够在不丢失数据包的情况下对数据进行一些处理?
答案 0 :(得分:3)
好吧,你没有无限的存储空间,所以,如果你连续运行的速度比数据包的速度慢,你将在某个时候丢失数据。
如果当然,如果你有相当数量的存储,并且平均你不会跑到后面(例如,你可能在爆发时跑得很慢但是在安静的时候你可以赶上),这将缓解这个问题。
一些网络嗅探器这样做,只需将原始数据写入文件以供以后分析。
这也是你可以使用的技巧,但不一定是文件。可以使用大量的内存结构,如循环缓冲区,其中一个线程(捕获线程)写入原始数据,另一个线程(分析)读取和解释。并且,因为每个线程只处理缓冲区的一端,所以你甚至可以在没有锁的情况下构建它(或使用非常短锁)。
这也可以很容易地检测出你的缓冲区是否用尽并引发某种错误,而不仅仅是在应用程序级别丢失数据。
当然,这一切都取决于您的“简单快速”捕获线程是否能够跟上流量。
澄清我的意思,修改你的process_packet
函数,使其除了将原始数据包写入大量循环缓冲区(检测溢出并相应地执行)之外什么都不做。这应该尽可能快,避免pcap本身丢弃数据包。
然后,有一个分析线程从队列中取出东西并完成以前在process_packet
中完成的工作(“删除标题并对数据进行一些处理”位。)
另一种可能的解决方案是提高pcap内部缓冲区大小。根据手册页:
到达捕获的数据包存储在缓冲区中,因此应用程序一到达就不必读取它们。
在某些平台上,可以设置缓冲区的大小;太小的大小可能意味着,如果捕获的数据包太多而快照长度不限制缓冲的数据量,如果缓冲区填满之前应用程序可以读取数据包,则可能会丢弃数据包它,虽然太大的大小可能会使用更多不可分页的操作系统内存,而不是防止数据包被丢弃。
缓冲区大小设置为
pcap_set_buffer_size()
。
唯一想到的另一种可能性是确保您对每个数据包执行的处理都尽可能优化。
将处理分解为收集和分析应该可以缓解不能跟上的问题,但仍然需要安静的时间来赶上。如果您的网络流量始终超出分析可以处理的范围,那么您所做的就是延迟问题。优化分析可能是保证永远不会丢失数据的唯一方法。