【问题标题】:Raw sockets VS Libpcap in a Linux C applicationLinux C 应用程序中的原始套接字 VS Libpcap
【发布时间】:2015-10-08 14:06:35
【问题描述】:

我正在开发一个 Linux C 应用程序,它的工作原理类似于 traceroute、发送 TCP/UDP 数据包并侦听传入的 TCP/UDP 应答数据包或 ICMP Time Exceeded 消息。

我想使用 libpcap 应该比处理原始套接字更容易,但是选择原始套接字而不是 libpcap 有什么要点吗?

有没有区别

  • 性能(我的应用获取传入数据包的速度)

  • CPU 使用率

  • 数据包丢失(我的主机收到数据包但我的应用没有收到数据包 - 由于某些延迟、超时过期或其他原因 - 特别是在 CPU 使用率高、网络流量高和网络性能低的情况下)?

还有其他我没有考虑到的差异吗?

如果应用在 Android 而不是 Linux 上运行,还有其他优点和缺点吗?

谢谢。

【问题讨论】:

    标签: linux android sockets traceroute pcap


    【解决方案1】:

    是的,有一个非常大的缺点:libpcap 不是你要找的。​​p>

    lipcap 本身对构建/分析 TCP、UDP、ICMP(甚至 IP)数据包的支持绝对为零。它根本不是它的用途。它可以设置在某些 TCP/UDP 等上匹配的过滤器,但通过了这一点,您必须自己进行所有解析。

    你应该看看pcap官方教程:

    http://www.tcpdump.org/pcap.html

    转到“实际嗅探”部分。查看 libpcap 在捕获与您的过滤器匹配的数据包时将调用的回调原型:

    void got_packet(u_char *args,
                    const struct pcap_pkthdr *header,
                    const u_char *packet);
    

    您将收到的数据包只是一个字符指针。您必须自己完成所有解析。随着教程的进行:

    但是你如何使用这个变量(在我们的 原型)?一个数据包包含许多属性,所以你可以想象, 它实际上不是字符串,而是结构的集合 (例如,一个 TCP/IP 数据包将有一个以太网头,一个 IP 头、TCP 头,最后是数据包的有效负载)。这个 u_char 指针指向这些结构的序列化版本。做 任何使用它,我们都必须做一些有趣的类型转换。

    然后你有一些代码可以做到这一点(通过一些简化使其不是 10 公里长,例如“以太网标头总是正好 14 个字节”——在 VLAN 上试试吧!)。从此以后,对于这个包解析,pcap不再提供任何代码。

    查看 pcap API。您是否看到与 IP/TCP/UDP/ICMP 相关的任何内容?没有。

    pcap_activate (3pcap) - activate a capture handle
    pcap_breakloop (3pcap) - force a pcap_dispatch() or pcap_loop() call to return
    pcap_can_set_rfmon (3pcap) - check whether monitor mode can be set for a not-yet-activated capture handle
    pcap_close (3pcap)   - close a capture device or savefile
    pcap_compile (3pcap) - compile a filter expression
    pcap_create (3pcap)  - create a live capture handle
    pcap_datalink (3pcap) - get the link-layer header type
    pcap_datalink_name_to_val (3pcap) - get the link-layer header type value corresponding to a header type name
    pcap_datalink_val_to_description (3pcap) - get a name or description for a link-layer header type value
    pcap_datalink_val_to_name (3pcap) - get a name or description for a link-layer header type value
    pcap_dispatch (3pcap) - process packets from a live capture or savefile
    pcap_dump (3pcap)    - write a packet to a capture file
    pcap_dump_close (3pcap) - close a savefile being written to
    pcap_dump_file (3pcap) - get the standard I/O stream for a savefile being written
    pcap_dump_flush (3pcap) - flush to a savefile packets dumped
    pcap_dump_fopen (3pcap) - open a file to which to write packets
    pcap_dump_ftell (3pcap) - get the current file offset for a savefile being written
    pcap_dump_open (3pcap) - open a file to which to write packets
    pcap_file (3pcap)    - get the standard I/O stream for a savefile being read
    pcap_fileno (3pcap)  - get the file descriptor for a live capture
    pcap_findalldevs (3pcap) - get a list of capture devices, and free that list
    pcap_fopen_offline (3pcap) - open a saved capture file for reading
    pcap_fopen_offline_with_tstamp_precision (3pcap) - open a saved capture file for reading
    pcap_free_datalinks (3pcap) - get a list of link-layer header types supported by a capture device, and free that list
    pcap_free_tstamp_types (3pcap) - get a list of time stamp types supported by a capture device, and free that list
    pcap_freealldevs (3pcap) - get a list of capture devices, and free that list
    pcap_freecode (3pcap) - free a BPF program
    pcap_get_selectable_fd (3pcap) - get a file descriptor on which a select() can be done for a live capture
    pcap_get_tstamp_precision (3pcap) - get the time stamp precision returned in captures
    pcap_geterr (3pcap)  - get or print libpcap error message text
    pcap_getnonblock (3pcap) - set or get the state of non-blocking mode on a capture device
    pcap_inject (3pcap)  - transmit a packet
    pcap_is_swapped (3pcap) - find out whether a savefile has the native byte order
    pcap_lib_version (3pcap) - get the version information for libpcap
    pcap_list_datalinks (3pcap) - get a list of link-layer header types supported by a capture device, and free that list
    pcap_list_tstamp_types (3pcap) - get a list of time stamp types supported by a capture device, and free that list
    pcap_lookupdev (3pcap) - find the default device on which to capture
    pcap_lookupnet (3pcap) - find the IPv4 network number and netmask for a device
    pcap_loop (3pcap)    - process packets from a live capture or savefile
    pcap_major_version (3pcap) - get the version number of a savefile
    pcap_minor_version (3pcap) - get the version number of a savefile
    pcap_next (3pcap)    - read the next packet from a pcap_t
    pcap_next_ex (3pcap) - read the next packet from a pcap_t
    pcap_offline_filter (3pcap) - check whether a filter matches a packet
    pcap_open_dead (3pcap) - open a fake pcap_t for compiling filters or opening a capture for output
    pcap_open_dead_with_tstamp_precision (3pcap) - open a fake pcap_t for compiling filters or opening a capture for output
    pcap_open_live (3pcap) - open a device for capturing
    pcap_open_offline (3pcap) - open a saved capture file for reading
    pcap_open_offline_with_tstamp_precision (3pcap) - open a saved capture file for reading
    pcap_perror (3pcap)  - get or print libpcap error message text
    pcap_sendpacket (3pcap) - transmit a packet
    pcap_set_buffer_size (3pcap) - set the buffer size for a not-yet-activated capture handle
    pcap_set_datalink (3pcap) - set the link-layer header type to be used by a capture device
    pcap_set_immediate_mode (3pcap) - set immediate mode for a not-yet-activated capture handle
    pcap_set_promisc (3pcap) - set promiscuous mode for a not-yet-activated capture handle
    pcap_set_rfmon (3pcap) - set monitor mode for a not-yet-activated capture handle
    pcap_set_snaplen (3pcap) - set the snapshot length for a not-yet-activated capture handle
    pcap_set_timeout (3pcap) - set the read timeout for a not-yet-activated capture handle
    pcap_set_tstamp_precision (3pcap) - set the time stamp precision returned in captures
    pcap_set_tstamp_type (3pcap) - set the time stamp type to be used by a capture device
    pcap_setdirection (3pcap) - set the direction for which packets will be captured
    pcap_setfilter (3pcap) - set the filter
    pcap_setnonblock (3pcap) - set or get the state of non-blocking mode on a capture device
    pcap_snapshot (3pcap) - get the snapshot length
    pcap_stats (3pcap)   - get capture statistics
    pcap_statustostr (3pcap) - convert a PCAP_ERROR_ or PCAP_WARNING_ value to a string
    pcap_strerror (3pcap) - convert an errno value to a string
    pcap_tstamp_type_name_to_val (3pcap) - get the time stamp type value corresponding to a time stamp type name
    pcap_tstamp_type_val_to_description (3pcap) - get a name or description for a time stamp type value
    pcap_tstamp_type_val_to_name (3pcap) - get a name or description for a time stamp type value
    

    (顺便说一句,构建数据包也没什么,只是发送一些)

    现在,关于原始套接字的想法:

    如果你想发送和接收 TCP 和 UDP,为什么不直接使用 TCP 和 UDP 套接字呢?

    最后,看看这里并用谷歌搜索最适合您需求的网络库:

    Best C/C++ Network Library

    【讨论】:

    • 谢谢jbm,性能上也有区别吗?我正在使用 libpcap 的同一应用程序的旧版本,而我的使用原始套接字。我已经体验到我的速度比旧的更快并且显示更多的数据包(特别是当有很多流量时),但我不确定这是库还是其他实现选择的问题。
    • “性能”问题不在主题范围内。你说“我想种西红柿”,然后问“我想用沙拉或土豆种子来做这件事,会有性能差异吗?”
    猜你喜欢
    • 2012-03-11
    • 1970-01-01
    • 2015-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多