我正在为一个流量非常大的网络编写监控程序(高清视频通过网络流式传输)。大多数数据包都非常大,我只想查看标头(仅限 IP 和 UDP/TCP)。当然,我想避免复制整个数据的开销。libpcap 是否一定要给我一份整个数据包的副本?如果是,是否有符合我需求的图书馆?
1 回答
这里似乎有两个问题:
- 标题中的那个,听起来好像是在询问 libpcap 是否复制了数据包;
- 正文中的那个,询问它是否总是复制整个数据包。
对于第一个问题:
使用 libpcap 在各种操作系统中运行的机制的任何代码可能至少完成了一个副本 - 从 mbufs/skbuff/STREAMS 缓冲区/任何到机制缓冲区的副本。对于 Linux,当不使用 tpacket 机制时,skbuff可能只是在接收队列中排队等待PF_PACKET
libpcap 正在使用的套接字。
可能还有另一个副本 - 从该缓冲区到用户区的副本;如果 libpcap 使用“零拷贝”机制,例如 Linux tpacket 机制(libpcap 1.0 及更高版本默认使用),则不会发生第二次拷贝。如果不使用零拷贝机制,就会发生这种情况。
但是,如果您使用pcap_next()
或pcap_next_ex()
在 Linux 系统上使用 tpacket 机制,则从内存映射缓冲区到私有缓冲区的单独副本;pcap_dispatch()
如果您使用or ,则不会发生这种情况pcap_loop()
。
对于第二个问题:
这就是“snaplen”参数pcap_open_live()
的pcap_set_snaplen()
用途 - 它允许您指定不应捕获超过“snaplen”字节的数据包数据,这意味着复制的字节数不超过那么多。
请注意,此长度包括链路层标头,并且可以包括“元数据”标头,例如您可能在 802.11 适配器上获得的radiotap标头。此标头可能是可变长度的(例如,在 802.11 上,802.11 标头是可变长度的,并且,如果您要获取 radiotap 标头,它们也是可变长度的)。
另外,IPv4 和 TCP 头都可以有选项,而 IPv6 数据包可以有扩展头,所以 IP 和 TCP 头的长度也可以是可变的。
这意味着您可能必须确定要使用的“最坏情况”快照长度;没有办法明确地说“不要给我任何超出 TCP/UDP 标头的东西”,您只能说“给我不超过 N 个字节”。