Необработанные сокеты VS Libpcap в приложении Linux C
Я разрабатываю приложение для Linux C, которое работает как traceroute, отправляя пакеты TCP/UDP и прослушивая входящие пакеты ответов TCP/UDP или сообщения ICMP Time Exceeded.
Я думаю, что должно быть проще использовать libpcap, чем иметь дело с необработанными сокетами, но есть ли смысл выбирать необработанные сокеты вместо libpcap?
Есть ли различия с точки зрения
производительность (как быстро мое приложение получает входящий пакет)
использование процессора
потеря пакетов (пакеты, полученные моим хостом, но не моим приложением - из-за некоторой задержки, истечения времени ожидания или по другой причине - особенно в случаях высокой загрузки ЦП, высокого сетевого трафика и низкой производительности сети)?
Есть ли другое отличие, которое я не учел?
Есть ли другие плюсы и минусы, если приложение работает на Android вместо Linux?
Спасибо.
1 ответ
Да, есть очень большой недостаток: libpcap - это не то, что вы ищете.
Сам по себе 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);
Пакет, который вы получите, является просто указателем на символ. Вы должны будете сделать все разбор этого самостоятельно. Как учебник продолжается:
Но как вы используете эту переменную (в нашем прототипе названную "package")? Пакет содержит много атрибутов, так что, как вы можете себе представить, это на самом деле не строка, а фактически набор структур (например, пакет TCP/IP будет иметь заголовок Ethernet, заголовок IP, заголовок TCP и, наконец,, полезная нагрузка пакета). Этот указатель u_char указывает на сериализованную версию этих структур. Чтобы использовать его, мы должны сделать интересное приведение типов.
И затем у вас есть некоторый код, который делает именно это (с некоторыми упрощениями, так что его длина не 10 километров, например, "заголовки Ethernet всегда ровно 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?
Наконец, посмотрите здесь и поищите в сети сетевые библиотеки, которые лучше всего соответствуют вашим потребностям: