linux - Linux C 应用程序中的原始套接字与 Libpcap

标签 linux android sockets traceroute pcap

我正在开发一个 Linux C 应用程序,其工作方式类似于 traceroute,发送 TCP/UDP 数据包并监听传入的 TCP/UDP 应答数据包或 ICMP 超时消息。

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

方面有区别吗
  • 性能(我的应用获取传入数据包的速度)

  • CPU 使用率

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

还有其他我没有考虑到的区别吗?

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

谢谢。

最佳答案

是的,有一个非常大的骗局:libpcap 不是您要找的。

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

你应该看看pcap官方教程:

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

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

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

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

But how do you make use of this variable (named "packet" in our prototype)? A packet contains many attributes, so as you can imagine, it is not really a string, but actually a collection of structures (for instance, a TCP/IP packet would have an Ethernet header, an IP header, a TCP header, and lastly, the packet's payload). This u_char pointer points to the serialized version of these structures. To make any use of it, we must do some interesting typecasting.

然后您有一些代码可以做到这一点(经过一些简化,使其长度不超过 10 公里,例如“以太网 header 始终恰好是 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 套接字?

最后,请查看此处并通过 google 搜索最适合您需求的网络库:

Best C/C++ Network Library

关于linux - Linux C 应用程序中的原始套接字与 Libpcap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33028696/

相关文章:

Java 创建一个新的 ObjectInputStream block

sockets - 如何从给定套接字读取协议(protocol)信息?

Linux 服务器与 .和 .. 目录

android - 使用默认调试 keystore 签名时抛出 SecurityException

android - 列表适配器共享

Android 源代码构建 : duplicate class

c - 如何处理 send() 中缓冲区长度输入和返回值大小不匹配?

linux - 如何在 bash 中同步处理 2 个范围/列表

linux - Exec --no-startup-id <command> 表示 "--"无效选项

Linux 上的 Java 应用程序