В процессе интеграции 1С с внешними сервисами, базами данных, торговым оборудованием или фискальными регистраторами часто требуется предварительно проверить, доступен ли конкретный сетевой узел и открыт ли на нем целевой порт. Выясним причину сложностей реализации такой проверки: во встроенном языке 1С отсутствуют низкоуровневые объекты для прямой работы с «сырыми» сокетами (Raw TCP/UDP Sockets). Однако задачу можно эффективно решить несколькими способами в зависимости от операционной системы и типа используемого протокола.
Разберем основные практические методы сканирования и проверки портов.
Если проверяемый порт предназначен для работы по протоколам HTTP/HTTPS (например, веб-сервисы, REST API, веб-серверы Apache/IIS), наиболее надежным и кроссплатформенным решением является встроенный объект HTTPСоединение. Посмотрим на пример кода с контролем таймаута:
Функция ПроверитьДоступностьВебПорта(Сервер, Порт, Таймаут = 3) Экспорт
Результат = Ложь;
Попытка
// Создаем соединение с минимальным таймаутом
Соединение = Новый HTTPСоединение(Сервер, Порт, , , , Таймаут);
Запрос = Новый HTTPЗапрос("/");
Ответ = Соединение.Получить(Запрос);
Результат = Истина;
Исключение
// Ошибка возникает при недоступности хоста или закрытом порте
Результат = Ложь;
КонецПопытки;
Возврат Результат;
КонецФункции
Преимущество метода: работает как на Windows, так и на Linux-серверах без вызова внешних процессов и зависимостей.
Рассмотрим вариант проверки произвольного TCP-порта на удаленном хосте в среде Windows. Для этого можно вызвать команду PowerShell через метод платформы ЗапуститьПриложение и проанализировать код возврата или результат выполнения команды.
Разберем по шагам вызов командлета Test-NetConnection:
-InformationLevel Quiet (возвращает True или False).powershell.exe.TcpClient.Connect.Посмотрим на пример выполнения проверки через запуск системной команды:
Функция ПроверитьПортPowerShell(Хост, Порт, ТаймаутСек = 3) Экспорт
Команда = СтрШаблон("powershell -Command ""$client = New-Object System.Net.Sockets.TcpClient; $iar = $client.BeginConnect('%1', %2, $null, $null); $wait = $iar.AsyncWaitHandle.WaitOne(%3000, $false); if($wait -and $client.Connected){ $client.EndConnect($iar); $client.Close(); exit 0 } else { exit 1 }""", Хост, Формат(Порт, "ЧГ="), ТаймаутСек);
КодВозврата = -1;
ЗапуститьПриложение(Команда, , Истина, КодВозврата);
Возврат (КодВозврата = 0);
КонецФункции
Если сервер 1С функционирует под управлением ОС Linux, вызов PowerShell неприменим. Проанализируем ситуацию в среде Linux: для проверки портов используются стандартные утилиты nc (Netcat) или встроенные возможности командного интерпретатора bash.
Функция ПроверитьПортLinux(Хост, Порт, ТаймаутСек = 2) Экспорт
// Использование встроенного сетевого псевдоустройства bash с ограничением по времени
Команда = СтрШаблон("timeout %1 bash -c 'cat < /dev/null > /dev/tcp/%2/%3'", ТаймаутСек, Хост, Формат(Порт, "ЧГ="));
КодВозврата = -1;
ЗапуститьПриложение(Команда, , Истина, КодВозврата);
Возврат (КодВозврата = 0);
КонецФункции
Рассмотрим альтернативный способ для устаревших Windows-систем с использованием компонента MSWINSOCK.Winsock.1. Данный метод работает синхронно в цикле ожидания изменения состояния сокета.
Функция СканироватьПортWinsock(Хост, Порт) Экспорт
Результат = Ложь;
Попытка
Сокет = Новый COMОбъект("MSWINSOCK.Winsock.1");
Сокет.RemoteHost = Хост;
Сокет.RemotePort = Порт;
Сокет.Connect();
Счетчик = 0;
// Состояние 7 означает успешное подключение (sckConnected)
Пока Сокет.State <> 7 И Счетчик < 20 Цикл
Приостановить(0.1);
Счетчик = Счетчик + 1;
КонецЦикла;
Если Сокет.State = 7 Тогда
Результат = Истина;
Сокет.Close();
КонецЕсли;
Исключение
Результат = Ложь;
КонецПопытки;
Возврат Результат;
КонецФункции
При реализации сетевой проверки важно учитывать технические нюансы работы сетевого стека:
TCP RST (сброс соединения). Если же пакеты блокируются фаерволом (DROP), ответ не возвращается, и процесс ожидает ответа до истечения системного или заданного таймаута.ФоновыеЗадания.Выполнить, чтобы не вызывать зависания интерфейса клиентского приложения 1С.