如果我想在Linux中嗅探数据包而不设置任何过滤器,我会看到2个选项。
使用libpcap
我自己使用原始套接字,例如https://www.binarytides.com/packet-sniffer-code-in-c-using-linux-sockets-bsd-part-2/
为什么libpcap
比自己使用原始套接字好?
三个原因:
1)更容易正确设置。
2)它是可移植的,甚至对于Windows来说也是如此,Windows使用了非常相似但又不同的套接字API。
3)更快。
1和2,IMO,不需要太多解释。我将深入探讨3。
要了解为什么libpcap(通常)更快,我们需要了解套接字API中的瓶颈。
libpcap倾向于避免的两个最大瓶颈是系统调用和副本。
如何执行是特定于平台的。
我将讲讲Linux的故事。
Linux,从2.0 IIRC开始,实现了所谓的AF_PACKET套接字家族,后来又实现了PACKET_MMAP。我没有确切地记得前者的好处,但是后者对于避免从内核复制到用户空间(内核端仍然有一些副本)和系统调用都是至关重要的。
在PACKET_MMAP中,您在用户空间中分配了一个大的环形缓冲区,然后将其关联到AF_PACKET套接字。该环形缓冲区将包含一些元数据(最重要的是,一个标记,指出是否准备好用户处理区域)和包内容。
[当数据包到达相关接口(通常是您将套接字绑定到的接口)时,内核会在环形缓冲区中进行复制,并将该位置标记为可用于用户空间*。如果应用程序正在套接字上等待,它将得到通知*。
所以,为什么这比原始套接字更好?因为设置套接字后您可以执行很少或不执行任何系统调用,这取决于是要对缓冲区本身进行繁忙轮询还是等待poll
,直到准备好几个数据包为止,并且因为不需要复制套接字的内部RX缓冲区连接到您的用户缓冲区,因为它已与您共享。
libpcap为您完成所有这一切。并在Mac,* BSD和几乎任何可为您提供更快捕获方法的平台上进行。
*在版本3上稍微复杂一些,在此版本中,粒度以“块”而不是数据包为单位。