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