В современной разработке все чаще встречаются задачи интеграции с внешними сервисами, которые работают в режиме реального времени. Если раньше стандартом был обмен файлами или HTTP-запросы, то сейчас многие API (особенно финансовые, биржевые или сервисы общепита) требуют работы по протоколу WebSocket. Это позволяет поддерживать постоянное соединение и мгновенно получать данные.
Однако, мы часто сталкиваемся с ситуацией, когда инфраструктура предприятия построена на старых релизах платформы 1С (например, 8.3.10 или еще старше). Обновление платформы ради одной функции может быть рискованным из-за большого количества "нетипового" кода, накопленного годами. Штатная поддержка WebSocket появилась только в платформе 8.3.25. Давайте разберем подробно, как решить эту задачу на старой платформе, проанализируем доступные архитектурные подходы и выберем оптимальные инструменты.
Прежде чем переходить к коду, давайте поймем суть проблемы. Протокол HTTP, с которым 1С отлично работает, основан на принципе "запрос-ответ". Мы спросили — нам ответили. WebSocket — это двусторонний канал. Сервер может прислать данные в любой момент, даже если мы его не спрашивали.
1С 8.3.10 (да и более новые версии в синхронном режиме) выполняет код последовательно. Если мы просто попытаемся "слушать" сокет в бесконечном цикле на клиенте, интерфейс пользователя "зависнет" намертво. Поэтому нам нужно искать решения, которые позволят получать данные асинхронно или имитировать это поведение.
Один из самых надежных способов, предложенный в обсуждении, — не пытаться заставить старую платформу делать то, для чего она не предназначена, а использовать промежуточное звено.
Суть метода заключается в развертывании микросервиса или использовании COM-подключения рядом с сервером 1С. Рассмотрим схему работы:
Почему это удобно? Старые версии 1С прекрасно умеют принимать входящие HTTP-запросы через механизм HTTPСервисы. Нам не нужно держать открытое соединение внутри сеанса пользователя.
Преимущества:
Если сервер 1С работает под управлением ОС Windows, мы можем воспользоваться мощью платформы .NET, которая уже есть в системе. Для этого часто используют обертку NetObjectToIDispatch или аналогичные разработки, позволяющие создавать классы .NET прямо из кода 1С.
В .NET Framework (начиная с версии 4.5) существует пространство имен System.Net.WebSockets. Давайте посмотрим, как мы можем это использовать. Нам потребуется создать объект ClientWebSocket.
Примерная логика инициализации соединения будет выглядеть так:
// Создаем обертку для работы с .NET
врап = Новый COMОбъект("NetObjectToIDispatch45");
// Создаем объект веб-сокета
Сокет = врап.СоздатьОбъект("System.Net.WebSockets.ClientWebSocket");
// Добавляем необходимые заголовки (одно из требований задачи)
// Используем CancellationToken (токен отмены) для асинхронных операций
ТокенОтмены = врап.СоздатьОбъект("System.Threading.CancellationToken");
// Устанавливаем заголовки, если API требует авторизации
Сокет.Options.SetRequestHeader("Authorization", "Bearer ВашТокен");
// Подключение (Uri - адрес wss://...)
URI = врап.СоздатьОбъект("System.Uri", "wss://api.example.com/stream");
Таск = Сокет.ConnectAsync(URI, ТокенОтмены.None);
// Ожидаем соединения (в реальном коде лучше делать это без Wait, чтобы не блокировать поток надолго)
Таск.Wait();
После установки соединения нам нужно читать данные. Поскольку методы чтения в .NET асинхронные (ReceiveAsync), а 1С — синхронная, нам придется либо использовать методы ожидания .Result или .Wait(), что заблокирует интерфейс, либо выносить этот код в фоновое задание.
Если вариант с .NET кажется сложным или вы работаете на Linux, стоит рассмотреть использование внешних компонент (ВК), написанных по технологии Native API. В частности, существуют ВК-обертки над библиотекой libcurl.
Библиотека cURL (libcurl) является стандартом де-факто для сетевых операций и поддерживает протоколы ws:// и wss://. Использование готовой компоненты снимает головную боль с реализацией протокола рукопожатия (handshake) и шифрования.
При использовании ВК алгоритм действий будет следующим:
ПодключитьВнешнююКомпоненту(...).Компонента.УстановитьЗаголовок("User-Agent", "1C-Client").Самый важный вопрос при работе с WebSocket внутри клиента 1С — как не "заморозить" кассира или менеджера, пока мы ждем сообщение от сервера.
Мы рекомендуем использовать один из двух подходов:
Если мы используем внешнюю компоненту, которая умеет накапливать сообщения во внутреннем буфере, мы можем настроить таймер в 1С.
// В модуле формы
Процедура ПриОткрытии()
// Подключаем ВК и соединяемся с сокетом
ПодключитьСокет();
// Запускаем опрос буфера каждые 0.5 секунды
ПодключитьОбработчикОжидания("ПроверитьСообщения", 0.5, Ложь);
КонецПроцедуры
Процедура ПроверитьСообщения()
// Спрашиваем у компоненты, есть ли новые данные
Данные = ОбъектВК.ПолучитьСледующееСообщение();
Если Данные <> Неопределено Тогда
ОбработатьДанные(Данные);
КонецЕсли;
КонецПроцедуры
Если данные нужны не конкретной открытой форме, а системе в целом (например, прием заказов в базу), лучше создать регламентное или фоновое задание.
В этом задании мы можем запустить "бесконечный" цикл (с разумными прерываниями), который будет висеть на соединении и ждать данные. При получении данных задание записывает их в РегистрСведений. А уже формы пользователей опрашивают этот регистр.
Интеграция 1С 8.3.10 с WebSocket — задача решаемая, хоть и требует обходных путей. Давайте подытожим варианты:
NetObjectToIDispatch и системные библиотеки .NET. Это позволяет писать код на 1С, но использовать возможности C#.При реализации обязательно помните про обработку обрывов связи (reconnect) и блокировку интерфейса. В старых релизах платформы пользовательский интерфейс однопоточен, поэтому любые длительные сетевые операции должны быть либо асинхронными, либо вынесенными в отдельные процессы.