WebSocket-Клиенты как хранилище значений

22.10.25

Разработка - Механизмы платформы 1С

Вы знали, что в WebSocket-клиенте можно хранить значения?

Предупреждение: материал носит исключительно познавательный характер.

Автор не предлагает делать так, как описано в статье, — он лишь проверил гипотезу и показал результат проверки.

Я уже рассказывал про WebSocket в двух статьях:


И вроде что ещё говорить?

Но есть одно «но»…

Пока 8 октября 2025 года я сидел и ждал заселения в отель — или хотя бы кого-то из знакомых, чтобы покататься по Неве, — мне в голову пришла гипотеза, которую я решил проверить.

Я достал ноутбук и набросал обработку, а дальше… дальше я расскажу, что из этого вышло.

 

Суть гипотезы

Заголовки у WebSocket-клиента — это соответствие.

 

 

В соответствии мы можем хранить многое, а самое интересное — что мы можем программно создавать столько WebSocket-клиентов, сколько захотим, присваивая им понятные для нас названия ключей. А дальше их можно использовать как константы, не изменяя конфигурацию.
 

Проверяем гипотезу.

Важное примечание:

WebSocket-клиент — это не соединение.

WebSocket-клиент — это описание параметров подключения к WebSocket-серверу.

Это важно понимать, так как мы будем использовать для хранения значений именно WebSocket-клиент.

 

1 Добавим WebSocket-клиент

Можно добавить его в основную конфигурацию или расширение.

Я добавлю в расширение:

 

 

Обратите внимание: я ничего не прописал в свойствах. Всё, что мне нужно, я заполню программно.
Напоминаю, нас интересуют только заголовки.

 

2 Предопределим WebSocket-клиент с понятным нам ключом

Нам понадобится имя «WS_Хранилище», которое мы придумали в первом пункте, и ключ.

Ключ WebSocket-клиента – это уникальное строковое значение. По данному значению будет происходить поиск WebSocket-клиента.

 

Вот так, ключ просто строка, которую написал вручную:

 

 

 
Немного кода:
&НаКлиенте
Процедура СоздатьХранилищеЗначений(Команда)
	
	Результат = СоздатьWSХранилище(ИмяВебсокета, КлючВебсокета);
	
	Если Не Результат Тогда 
		
		Сообщить("нужно проверить имя объекта метаданных или ключ не уникален");	
		
	КонецЕсли;
	
КонецПроцедуры

// Предопределяем WebSocket-клиент
//
// Параметры:
//  ИмяОбъектаМетаданныхWS	 - Строка - Имя объекта метаданных WebSocket-клиенты
//  КлючWS					 - Строка - Уникальный ключ WebSocket-клиента 
// 
// Возвращаемое значение:
//  Булево - Если Истина WebSocket-клиент предопределен, Ложь нужно проверить имя объекта метаданных или ключ не уникален
//
&НаСервере
Функция СоздатьWSХранилище(Знач ИмяОбъектаМетаданныхWS, Знач КлючWS) Экспорт
	
	Результат = Ложь;
	
	WSОбъектаМетаданных = Метаданные.WebSocketКлиенты.Найти(ИмяОбъектаМетаданныхWS);	
	Если WSОбъектаМетаданных <> Неопределено Тогда 
		WSКлиент = WebSocketКлиенты.НайтиПоКлючу(КлючWS);
		
		Если WSКлиент = Неопределено Тогда  
			
			WSКлиент = WebSocketКлиенты.СоздатьКлиента(WSОбъектаМетаданных, КлючWS); 	
			WSКлиент.Записать();
			
			Результат = Истина;	
			
		КонецЕсли;		
		
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

 

Пояснение:

Первоначально мы ищем объект метаданных WebSocket-клиенты по имени. Если не находим — значит, ничего не делаем.

Далее мы ищем по ключу WebSocket-клиент. Ключ уникален, и если с таким ключом уже есть запись, тогда мы не сможем предопределить WebSocket-клиент.

 

Как можно проверить, что мы предопределили WebSocket-клиент?

Например, можно воспользоваться типовой обработкой:

 

 

Или выполнить код:

WSКлиент = WebSocketКлиенты.НайтиПоКлючу(КлючWS);

 

3 Запишем свои значения в предопределенный WebSocket-клиент

Как я уже говорил, будем использовать заголовки.

Для начала запишем несколько значений. Я специально для примера создал справочник «Товары», в котором будет только наименование.

Создам в этом справочнике три элемента:

 

 

Также на форме я создам таблицу значения с двумя колонками:

 

 

 
И добавляем команду для записи значений:
&НаКлиенте
Процедура ЗаписатьЗначения(Команда)
	
	ЗаписатьДанныеWSХранилище(КлючВебсокета); 
	
КонецПроцедуры

// Добавляем данные в предопределенный WebSocket-клиент
//
// Параметры:
//  КлючWS	 - Строка - Уникальный ключ WebSocket-клиента 
//
&НаСервере
Процедура ЗаписатьДанныеWSХранилище(Знач КлючWS) Экспорт
	
	ВебсокетКлиент = WebSocketКлиенты.НайтиПоКлючу(КлючWS); 
	Если ВебсокетКлиент <> Неопределено Тогда 
		Для Каждого текЭлемент из Список Цикл 
			ВебсокетКлиент.ПараметрыСоединения.Заголовки.Вставить(текЭлемент.Ключ,текЭлемент.Значение);		
		КонецЦикла;		
		ВебсокетКлиент.Записать();
	КонецЕсли;     
	
КонецПроцедуры

 

Пояснение:

Ищем по ключу WebSocket-клиент и вставляем в него заголовки, обходя таблицу значений.

 

Заполняем ключ ранее предопределенного клиента, добавляем значения и нажимаем «Записать значения»:

 

 

И вот тут самое интересное.

Если мы откроем стандартную обработку, то увидим, что ключи и значения с типом строка:

 

 

Но это иллюзия 😉

В стандартной обработке просто у таблицы значения колонки с типом строка:

 

 

На самом же деле, если мы программно получим значения, то увидим совсем другую картину.

 
Выполним вот такой код:
&НаКлиенте
Процедура ПрочитатьДанные(Команда)
	
	ПрочитатьДанныеWSХранилище(КлючВебсокета);
	
КонецПроцедуры

// Прочитать данные из предопределенного WebSocket-клиент
//
// Параметры:
//  КлючWS	- Строка - Уникальный ключ WebSocket-клиента
//
&НаСервере
Процедура ПрочитатьДанныеWSХранилище(Знач КлючWS) Экспорт
	
	Если Список.Количество() > 0 Тогда 
		Список.Очистить();
	КонецЕсли;	
	
	ВебсокетКлиент = WebSocketКлиенты.НайтиПоКлючу(КлючWS); 
	Если ВебсокетКлиент <> Неопределено Тогда 
		Для Каждого текЭлемент из ВебсокетКлиент.ПараметрыСоединения.Заголовки Цикл 
			новаяСтрока = Список.Добавить();
			
			новаяСтрока.Ключ = текЭлемент.Ключ;
			новаяСтрока.Значение = текЭлемент.Значение;	
		
		КонецЦикла;
		
	КонецЕсли;

КонецПроцедуры

 

Пояснение:

Очищаем список от введенных ранее значений. Ищем по ключу WebSocket-клиент, заполняем таблицу на основании заголовков WebSocket-клиента.

 

 

Как вам такое?

Но мне было интересно зайти дальше…

Мы же можем сохранять хранилище значений, а значит, мы можем записывать в заголовки: структуры, картинки, обработки…

Что угодно.

 

Давайте проверим

 
Пишем вот такой код:
&НаКлиенте
Процедура ЗаписатьСтруктуруВХЗ(Команда)
	
	ЗаписываемаяСтруктура = Новый Структура("Тест,Тест2", 11,"Вася");
	НовыйМассив = Новый Массив;
	НовыйМассив.Добавить(1);
	НовыйМассив.Добавить("текст");
	ЗаписываемаяСтруктура.Вставить("МассивДоКучи",НовыйМассив);
	
	ЗаписатьДанныеВЗаголовокПоКлючу(КлючВебсокета, КлючХранилища, ЗаписываемаяСтруктура);
	
КонецПроцедуры

// Записываем данные в заголовок предопределенного WebSocket-клиента по ключу
//
// Параметры:
//  КлючWS		 - Строка - Уникальный ключ WebSocket-клиента 
//  КлючЗаголовка - Строка - Имя заголовка
//  Значение	 - Произвольный	 - Записываемые данные
//
&НаСервере
Процедура ЗаписатьДанныеВЗаголовокПоКлючу(Знач КлючWS, Знач КлючЗаголовка, Знач Значение) Экспорт
	
	ВебсокетКлиент = WebSocketКлиенты.НайтиПоКлючу(КлючWS); 
	Если ВебсокетКлиент <> Неопределено Тогда 
		
		ЗначениеЗаголовка = Новый ХранилищеЗначения(Значение);
		ВебсокетКлиент.ПараметрыСоединения.Заголовки.Вставить(КлючЗаголовка, ЗначениеЗаголовка);		
		ВебсокетКлиент.Записать();
		
	КонецЕсли;
		
КонецПроцедуры

 

Пояснение:

Создаем структуру с различными значениями, а далее ищем по ключу WebSocket-клиент и записываем в него новый заголовок с типом ХранилищеЗначения.

 

 

А теперь прочитаем, что мы там записали

 
Код для чтения:
&НаКлиенте
Процедура ПрочитатьДанныеХЗ(Команда)
	Результат = ПрочитатьДанныеЗаголовокаПоКлючу(КлючВебсокета, КлючХранилища);
КонецПроцедуры

// Прочитать данные заголовка по ключу
//
// Параметры:
//  КлючWS		 - Строка - Уникальный ключ WebSocket-клиента 
//  КлючЗаоловка - Строка - Имя заголовка
// 
// Возвращаемое значение:
//  Произвольный - значение заголовка
//
&НаСервере
Функция ПрочитатьДанныеЗаголовокаПоКлючу(Знач КлючWS, Знач КлючЗаголовка) Экспорт
	
	Результат = Неопределено;
	
	ВебсокетКлиент = WebSocketКлиенты.НайтиПоКлючу(КлючWS); 
	Если ВебсокетКлиент <> Неопределено Тогда 
		
		ТекущийЗаколовок = ВебсокетКлиент.ПараметрыСоединения.Заголовки[КлючЗаголовка];		
		Если ТекущийЗаколовок <> Неопределено Тогда 
			Если ТипЗнч(ТекущийЗаколовок) = Тип("ХранилищеЗначения") Тогда 
				Результат = ТекущийЗаколовок.Получить();
			Иначе
				Результат = ТекущийЗаколовок;
			КонецЕсли; 
		КонецЕсли;	
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

 

 

 

Хочу добавить, какие фишки у этого метода есть:

1 В отличие от констант тут нет привязки к ролям.

2 Нам не надо лазить в конфигуратор чтобы создать константу.

3 Просто интересная фича.

 

Очевидные минусы:

1 Непонятно, как это будет в будущем.

2 Незнающий человек долго будет искать, а потом проклинать вас.

3 WebSocket-клиент придуман не для хранилища значений.

 

Повторюсь: -"Я не призываю так делать".

Я лишь "утолил жажду инженера" и поковырялся чуть дальше, чем нужно 😉

 

На этом статью заканчиваю, если понравилось, то не стесняйтесь нажимать «+».

 

Все материалы выложены в GitHub:

WebSocketIn1C на GitHub

Вступайте в нашу телеграмм-группу Инфостарт

WebSocket WebSocket-клиент Константы ХранилищеЗначения Фичя значения заголовки заголовок 8.3.27 ключ платформа Архитектура

См. также

Механизмы платформы 1С Программист Бесплатно (free)

Разберем 15 мифов о работе платформы «1С:Предприятие 8» – как распространенных, так и малоизвестных. Начнем с классики: «Код, написанный в одну строку, работает быстрее, чем многострочный». Так ли это на самом деле?

16.07.2025    21438    TitanLuchs    106    

136

Механизмы платформы 1С Работа с интерфейсом Программист Стажер 1С v8.3 Бесплатно (free)

Про ООП в 1С и о том, как сделать свой код более кратким и выразительным при помощи использования текучего интерфейса (fluent interface).

03.02.2025    12264    bayselonarrend    126    

64

Механизмы платформы 1С WEB-интеграция Программист 1С v8.3 Бесплатно (free)

В платформе 8.3.27 появилась возможность использовать WebSocket-клиент. Давайте посмотрим, как это все устроено и чем оно нам полезно.

14.01.2025    20884    dsdred    77    

134

Механизмы платформы 1С Программист Стажер 1С v8.3 1C:Бухгалтерия Бесплатно (free)

Эта небольшая статья - некоторого рода шпаргалка по файловым потокам: как и зачем с ними работать, какие преимущества это дает.

23.06.2024    21086    bayselonarrend    22    

169

Механизмы платформы 1С Программист Стажер 1С v8.3 1C:Бухгалтерия Бесплатно (free)

Пример использования «Сервисов интеграции» без подключения к Шине и без обменов.

13.03.2024    11860    dsdred    22    

84

Механизмы платформы 1С Программист Стажер 1С v8.3 Бесплатно (free)

Все мы используем массивы в своем коде. Это один из первых объектов, который дают ученикам при прохождении обучения программированию. Но умеем ли мы ими пользоваться? В этой статье я хочу показать все методы массива, а также некоторые фишки в работе с массивами.

24.01.2024    43318    YA_418728146    35    

75
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. aximo 2503 22.10.25 09:25 Сейчас в теме
2. dsdred 4060 22.10.25 09:29 Сейчас в теме
(1) рад, что стаья понравилась
shapapro; +1 Ответить
3. booksfill 22.10.25 10:06 Сейчас в теме
Я так понял разговор идет про "констатанту".
Если так, то надо ли так понимать, что данные в хранилище значений (впрочем, и любые другие), лежащем в сокете, будут доступны и после завершения сеанса, или перезагрузки севера?


"Непонятно, как это будет в будущем."
Согласен.
В спецификации размер заголовков не ограничен, однако на практике (например, для предотвращения DDOS атак - но это не точно) размер режется на HHTP сервере. Обычно это до 4Кб.

Поскольку 1С имеет свой сервер и просто начинает закручивать гайки по безопасности, то не исключено, что ограничения по типу и размеру данных будут добавлены непосредственно в сам сокет.
Причем без объявления войны

Но строки-то никто резать, в разумных пределах, не будет, так что, спасибо за статью, если не увлекаться, думаю можно использовать и на практике. Вот только см. первый вопрос...
4. dsdred 4060 22.10.25 10:18 Сейчас в теме
(3)
Я так понял разговор идет про "констатанту".
Если так, то надо ли так понимать, что данные в хранилище значений (впрочем, и любые другие), лежащем в сокете, будут доступны и после завершения сеанса, или перезагрузки севера?


Я специально обозначил, что речь идет про WebSocket-клиент, а не соединение ;)
предопределенный программно клиент хранится в SQL таблице "websocketclients" и соответственно не зависит от перезапуска сервера.

Отвечая на вопрос кратко: сохранится и после выключения\перезагрузки сервера
SerVer1C; ixijixi; ardn; +3 Ответить
5. booksfill 22.10.25 11:51 Сейчас в теме
(4) Спасибо. Понял.
А можно еще вопрос?
Чем такой вариант лучше, по сравнению с хранением настроек, например, в регистре сведений?
Только тем, что РС надо еще создать, а сокеты уже вот они, из коробки, или сокеты еще и более легковесное решение?

Просто прикидываю как-бы такую находку применить на практике. Интересно же. :)
6. dsdred 4060 22.10.25 11:57 Сейчас в теме
(5)
Чем такой вариант лучше, по сравнению с хранением настроек, например, в регистре сведений?
Только тем, что РС надо еще создать, а сокеты уже вот они, из коробки, или сокеты еще и более легковесное решение?

Тут сложно сказать, что лучше или хуже. Тут быстрее и гибче получается. Один клиент заменяет кучу всего ))
Опять же удалять клиента программно тоже быстрее чем регистр чистить.

Повторюсь. Делал эксперимент ради интереса. ;)
7. PilPatn 22.10.25 13:58 Сейчас в теме
8. dsdred 4060 22.10.25 14:00 Сейчас в теме
(7) рад, что понравилось
9. RocKeR_13 1457 22.10.25 17:23 Сейчас в теме
Пока больше академическое значение у данного открытия, нежели практического, на мой субъективный взгляд) Для какого-то небольшого пула информации часто использую БСПшный регистр сведений БезопасноеХранилищеДанных и методы ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище, ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища и ОбщегоНазначения.УдалитьДанныеИзБезопасногоХранилища.

На самый худой случай - ХранилищеОбщихНастроек. Многие скептически относятся к ХранилищеОбщихНастроек, но вот уже 8 лет как у одного из клиентов просто огромная куча настроек в нем хранится и никаких потерь данных зафиксировано не было.
10. dsdred 4060 22.10.25 17:25 Сейчас в теме
(9) дак я же и пишу утодил жажду инженера ;)
13. RocKeR_13 1457 23.10.25 09:38 Сейчас в теме
(10) посмотрим, может кто-то что дельное на основе этого придумает)
11. Avatarzorro 61 23.10.25 02:20 Сейчас в теме
Прикольно. Как бы не было по классике, что в платформу костыль зашьют без документирования и все это поломается
12. dsdred 4060 23.10.25 06:47 Сейчас в теме
(11) все может быть. Но я получил в очередной раз удовольствие поковырявшись в этом всем ;)
Для отправки сообщения требуется регистрация/авторизация