Пинг-утилита на Delphi с многопоточностью
Многопоточная пинг-утилита на Delphi позволяет одновременно проверять доступность сетевых узлов и измерять задержку до них. В последовательной реализации каждый адрес блокирует интерфейс на время ожидания ответа, поэтому много удалённых хостов превращают проверку в долгий процесс. Параллельный вариант разделяет эти ожидания между рабочими потоками и возвращает результаты по мере их поступления.
Практичная конструкция состоит из независимого сетевого модуля, планировщика задач, накопителя результатов и слоя вывода. Сетевой модуль отвечает за конкретный способ отправки ICMP-пакетов, планировщик ограничивает число одновременно работающих целей, а результаты передаются в поток интерфейса через очередь. Такое разделение позволяет менять платформенную реализацию и формат вывода, не переписывая основную логику проверки.
Отдельно обрабатываются разрешение имени, тайм-аут, повторные запросы и отмена работы. Именно эти детали чаще всего отличают учебный пример от утилиты, которой удобно пользоваться при диагностике сети из Алматы или любого другого города.
Сетевой протокол и модель измерений
Базовый механизм диагностики использует сообщения ICMP типа Echo Request и Echo Reply. Отправленный пакет содержит идентификатор сессии, номер последовательности и необязательные данные для сверки с ответом. По разнице монотонных отметок времени вычисляется время обратного пути, а счётчик ответов показывает, какая доля запросов вернулась.
Исчезновение ответа не доказывает, что узел выключен: его мог отбросить межсетевой экран, маршрутизатор или оператор связи. Поэтому результат разумно разделять на успешный ответ, сетевой тайм-аут и ошибку разрешения адреса, не объединяя разные причины в один статус.
Платформенный модуль реализует одинаковый контракт проверки, а пользовательский код работает с едиными типами задержки, счётчиками и текстами ошибок.
Архитектура приложения и потоков
Ядро утилиты лучше собрать как консольное приложение или отдельный модуль без прямой зависимости от VCL и FireMonkey. В нём удобно описать параметры адреса, число попыток, интервал и тайм-аут, а также результат проверки. Повторное использование такого модуля упрощает создание графической версии и мобильного приложения.
Базовые типы можно описать без привязки к компонентам интерфейса:
type
TProbeOptions = record
Host: string;
Count: Integer;
TimeoutMs: Cardinal;
IntervalMs: Integer;
end;
TProbeResult = record
Host: string;
Address: string;
Replies: Integer;
LastRttMs: Cardinal;
ErrorText: string;
end;
Для фоновой работы подходят TTask, пул потоков или собственные экземпляры TThread. Предпочтительно использовать ограниченное число рабочих задач: в современных версиях Delphi обработчики графического интерфейса получают данные через TThread.ForceQueue, поэтому потоки не обращаются к элементам формы напрямую.
Жизненный цикл задач должен зависеть от явного запроса остановки. Проверка флага отмены выполняется между пакетами и во время пауз, а отдельное ожидание сокета всегда ограничено тайм-аутом. Исключения перехватываются внутри рабочей процедуры, и после завершения освобождаются ресурсы. Это предотвращает зависание программы при разрыве связи или ошибке доступа к сокету.
Выполнение ICMP-запросов
В Windows основной путь строится на функции IcmpSendEcho из IP Helper API. Она принимает числовой IPv4-адрес, необязательные данные, размер буфера и тайм-аут, а возвращает число ответов вместе с массивом структур IP_ECHO_REPLY. Буфер выделяется отдельно и обнуляется: первые четыре байта содержат счётчик ответов, после которого идут структуры с выравниванием под разрядность процесса. Обычные эхо-запросы не требуют запуска утилиты с правами администратора.
На Linux и macOS применяется отдельный модуль с сырым сокетом и протоколом ICMP. Такой сокет обычно требует root либо выделенного Linux-разрешения CAP_NET_RAW, поэтому наличие привилегий нужно проверять до запуска проверок. Ответ читается с тайм-аутом через poll или select, а длительность измеряется монотонными часами, чтобы перевод системного времени не искажал результат.
Имя узла разрешается заранее через DNS-клиент или платформенный getaddrinfo, после чего платформенный слой получает готовый адрес. Ошибки DNS учитываются отдельно от недоступности уже разрешённого адреса. При поддержке IPv6 протокол и формат адреса выбираются явно, чтобы не передавать IPv4-значение в функцию, ожидающую IPv6.
Параллельные проверки узлов
Планировщик задаёт верхнюю границу параллелизма независимо от количества целей в списке. Один рабочий поток обрабатывает один адрес, а заданное число пакетов отправляет последовательно с нужной паузой; одновременно другие потоки занимаются остальными адресами. Такой вариант сохраняет порядок результатов внутри каждой цели и не создаёт тысячу потоков ради тысячи строк входных данных.
Разрешение DNS лучше вынести в отдельный ограниченный пул: ожидание сервера имён не должно занимать ресурсы, предназначенные для приёма ICMP-ответов. После преобразования адресов планировщик запускает только сетевые проверки, поэтому длительные задержки имен сервера не смешиваются с задержкой маршрута.
Состояние общей коллекции защищают синхронизацией либо передают результат по очереди без конкурентной записи. Порядок строк восстанавливают по исходному индексу цели, а готовность завершения определяют по счётчику задач, а не по факту показа последнего ответа. Эти меры снижают риск гонок и потери результатов при быстром завершении программы.
Результаты, интерфейс и управление
Для каждого адреса сохраняют число отправленных и принятых пакетов, последнее или среднее время ответа, адрес узла и категорию ошибки. Коды состояния Windows и признаки истечения времени POSIX переводят в понятные статусы, не смешивая их с исключением сокета. Значение TTL добавляют только тогда, когда оно реально доступно выбранной реализации.
Графический слой FireMonkey или VCL получает пакет обновлений из очереди и меняет прогресс уже в основном потоке. Так интерфейс остаётся отзывчивым, а строки результатов могут сортироваться по задержке, адресу или числу потерь. Для консольного варианта удобно накапливать завершённые строки и выводить их в исходном порядке либо сразу по завершении отдельной цели.
Параметры командной строки задают список или диапазон адресов, количество запросов, паузу, тайм-аут, предел потоков и формат вывода. Значения проверяются на допустимые диапазоны до запуска потоков, а пользовательский ввод не передаётся командной оболочке. Команда остановки должна завершать ожидания и освобождать сокеты независимо от текущего результата.
Проверка качества и безопасность
Автоматические проверки охватывают локальный адрес, шлюз, внешний узел, неверное имя и недоступный маршрут. Отдельно воспроизводятся потеря части ответов, нулевая задержка и превышение тайм-аута. IPv4 и IPv6 проверяются независимо, чтобы ошибка одного протокола не скрывала работоспособность другого.
Нагрузочные тесты измеряют расход памяти, число активных потоков и время завершения при десятках и сотнях целей. Особое внимание уделяют гонкам при одновременном обновлении интерфейса, взаимным блокировкам и утечкам сокетов. Повторные запуски с включённым анализатором помогают убедиться, что потоки действительно завершились, а результаты не зависают в очереди.
Привилегии запрашивают только там, где они обязательны для конкретного сокета, а собранные данные не содержат лишней полезной нагрузки. Пинг проверяет доступность узла на сетевом уровне, но не подтверждает работу приложения или базы данных за ним. Для такой проверки используют отдельный HTTP-запрос с ожидаемым ответом.
Различия платформ и практическое применение
Настольные версии Delphi для Windows, Linux и macOS могут использовать разные сетевые модули при общей модели потоков. Мобильные ограничения строже: приложение на Kotlin обычно не получает прямой доступ к сырым ICMP-сокетам, а Swift предоставляет сетевые API без возможности произвольно отправлять такие пакеты. Поэтому для Android и iOS практичнее проверять достижимость через разрешённый транспорт, а точные ICMP-измерения оставлять настольной версии или согласованному серверному компоненту.
Такой подход хорошо согласуется с кроссплатформенной разработкой, представленной на сайте разработчика. В профессиональном профиле Равиля Зарипова собраны проекты на Delphi, FireMonkey, Kotlin и Swift, а также серверные решения на PHP и работа с базами данных. Этот опыт полезен для выбора безопасной архитектуры, которая не переносит ограничения одной платформы на все остальные.
| Платформа | Механизм проверки | Ограничение |
|---|---|---|
| Windows | IcmpSendEcho |
Обычные эхо-запросы не требуют повышения прав |
| Linux | Сырой ICMP-сокет | Обычно нужны root или CAP_NET_RAW |
| macOS | Сырой ICMP-сокет | Обычно нужны права администратора |
| Android | HTTP или TCP-проверка в Kotlin | Прямой ICMP обычному приложению недоступен |
| iOS | HTTP или TCP-проверка в Swift | Произвольные ICMP-пакеты недоступны |
Главная ценность многопоточной реализации — не само число потоков, а независимость сетевой проверки от интерфейса. Единый контракт результатов, ограниченный пул задач, корректное завершение и платформенные ограничения позволяют одной архитектуре оставаться предсказуемой как на рабочем компьютере, так и на сервере, где запуск сырых сокетов часто запрещён.