Пример реализации обмена с оборудованием через winsocket на управляемых формах по протоколу TCP

09.01.17

Интеграция - Периферийные устройства

Объединяя опыт коллег с данного ресурса, хочу поделиться своим решением с подключением контроллера контроля доступа к 1С УНФ. Здесь описан метод без использования ActiveX, который не работает на УФ.

Задача была по поводу наладки обмена информацией между 1С УНФ и контроллера управления доступа клиентов. Имеется описание протокола для связи с контроллером по TCP. Контроллер может работать в режиме сервера, прослушивая определенный порт принимая с него команды и отправляя обратно ответы. Решил использовать WinSocket, благо информации много.

Вот неплохая публикация, где рассматриваются режимы клиента и сервера с использованием ActiveX://infostart.ru/public/119982/

Одна беда - УФ. ActiveX  - не поддерживается.

Итак приступим.

Прикручиваем к УФ
ActiveX не прижился на УФ. Метод с офисом, который рассматривался здесь - сложноват, поэтому подключаем Winsocket как COMобъект.

Как же его хранить? Будем хранить его в параметрах сеанса. Оттуда он доступен и клиенту и серверу. 

Процедура ПриОткрытииНаСервере()
    Контроллер = Новый COMОбъект("mswinsock.winsock"); 
    ПараметрыКонтроллера = Новый Структура("Адрес, Порт");
    ПараметрыКонтроллера.Адрес = "xxx.xxx.xxx.xxx";
    ПараметрыКонтроллера.Порт = "pppp";
    
    СтруктОбъекта = Новый Структура("Контроллер",Контроллер);
    ПараметрыСеанса.Z5=ПоместитьВоВременноеХранилище(СтруктОбъекта,Новый УникальныйИдентификатор());
    ИнициализироватьПодключение(ПараметрыКонтроллера);
КонецПроцедуры

Заметим, что COMобъект мы спрятали в структуру. Как уже обсуждалось на Инфостарте, COMобъекты не поддерживают сериализацию. А если "спрятать" его в структуру, ошибок не будет:

 СтруктОбъекта = Новый Структура("Контроллер",Контроллер);
    ПараметрыСеанса.Z5=ПоместитьВоВременноеХранилище(СтруктОбъекта,Новый УникальныйИдентификатор());

Рассмотрим подключение. Отдельное спасибо Андрею, автору публикации: //infostart.ru/public/119982/ и участникам обсуждения за знакомство с winsocket.

&НаСервере
Процедура ИнициализироватьПодключение(ПараметрыПодключения)    
    ws = ПолучитьИзВременногоХранилища(ПараметрыСеанса.Z5).Контроллер;
    Если ws.State <> 7 тогда
         Если ws.State <> 0 Тогда
            ws.Close();
        КонецЕсли;
        
        ws.RemoteHost = СокрЛП(ПараметрыПодключения.Адрес);
        ws.RemotePort = СокрЛП(ПараметрыПодключения.Порт);
        ws.Connect();
    Иначе
        ws.Close();
        
        ws.RemoteHost = СокрЛП(ПараметрыПодключения.Адрес);
        //        ws.RemoteHostIP = СокрЛП(ПараметрыПодключения.Адрес);
        ws.RemotePort = СокрЛП(ПараметрыПодключения.Порт);
        
        ws.Connect();
    КонецЕсли;
    Объект.Статус = ws.state; //Сохраняем статус чтобы отображать его на форме
    
КонецПроцедуры

Все, подключились. При открытии формы нашей обработки мы хотим получить некоторые данные с контроллера.

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

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

&НаКлиенте
Процедура ПриОткрытии(Отказ) 

//Мы будем использовать сканер и считыватель
	ИспользоватьПодключаемоеОборудование=Истина;
	// ПодключаемоеОборудование
	МенеджерОборудованияКлиентПереопределяемый.НачатьПодключениеОборудованиеПриОткрытииФормы(ЭтаФорма, "СканерШтрихкода,СчитывательМагнитныхКарт");
	// Конец ПодключаемоеОборудование
//--------------------------------------------
	ПриОткрытииНаСервере();
	
	//Заблокируем форму от изменений
	УправлениеДоступностью(Ложь);
	
	//Пошлем первую команду на получение списка контроллеров
	ПодключитьОбработчикОжидания("ПолучитьСтатус",10);
	Объект.ТипКоманды = "20";
	Объект.Команда = "ПолучитьАдресКонтроллера";
	Объект.ТекстСообщения = "00 08 08 01 00 00 00 00";
	ПодключитьОбработчикОжидания("ВыполнитьКоманду",1);
	
	//Подключим периодический опрос контроллеров
	Объект.НомерВыполняемойКомандыОпроса = 1;
	ПодключитьОбработчикОжидания("ПериодическийОпрос",1);   //здесь могут крутиться несколько команд, которые получают события и отправляют изменения
	
КонецПроцедуры

Сама процедура отправки команды, которая в нашем случае вызывается многократно 1 раз в секунду, на случай, если контроллер чем-то занят.

&НаКлиенте
Процедура ВыполнитьКоманду()
    
    ПолучитьСтатус();
    Элементы.Статус.Заголовок = Объект.Статус;
    Если Объект.Статус = 0 Тогда   //Не подключено 
        ПриОткрытииНаСервере();
        Возврат;
    ИначеЕсли Объект.Статус = 6 Тогда // еще идет подключение
        Возврат;
    КонецЕсли;
    УправлениеДоступностью(Ложь); //ничего нельзя делать на форме
    Результат = ОтправитьДанные();   // Ниже функция отправки
    Элементы.Статус.Заголовок = Объект.Статус;
    Если Результат Тогда
        Объект.Лог = Формат(ТекущаяДата(),"ДЛФ=DT") + ": " + Объект.Команда +" --> " + Символы.ПС + Объект.Лог;
        Объект.Лог = Объект.ТекстСообщения + Символы.ПС + Объект.Лог;
        ОтключитьОбработчикОжидания("ВыполнитьКоманду"); //Команда выполнилась, отключаем этот обработчик
        ПодключитьОбработчикОжидания("ПолучитьОтвет",1); //Подключаем ожидание ответа Многократно    
    Иначе
        Если Объект.Статус = 9 Тогда //ошибка, не расшифровать нафиг
            ПриОткрытииНаСервере(); //реконнект (кстати не помогает. Только отключение кабеля)
        КонецЕсли;
    КонецЕсли;       
    
КонецПроцедуры

Функцию ОтправитьДанные() мы рассмотрим ниже, а пока из кода видно, что после отправки команды на контроллер мы подключаем второй обработчик ожидания на получение ответа контроллера. ActiveX winsocket, который мы в силу обстоятельств не можем использовать, имеет очень важное событие WinSocketDataArrival, которое возникает при получении данных. Нам придется обходиться без него. Мы просто 1 раз в секунду будем читать возможно полученные ответы.

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

Собственно функция отправки:

&НаСервере
Функция ОтправитьДанные()
    Результат = Ложь;
    Контроллер = ПолучитьИзВременногоХранилища(ПараметрыСеанса.Z5).Контроллер; //получили winsocket из параметров сеанса
    buff = ПреобразоватьДляОтправки(Объект.ТекстСообщения);  // преобразование в массив HEX требуется для моего контроллера
    buff[0] = "&H" + Объект.ТипКоманды;
    ВОтправку = "";
    Для н = 0 По buff.Количество()-1 Цикл
        ВОтправку =ВОтправку + buff[н] + " ";    
    КонецЦикла;

    Объект.Статус = Контроллер.State;
    
    Если Контроллер.State = 7 тогда //Подключились удачно, отправляем данные
        Попытка
            Для н = 0 По buff.Количество()-1 Цикл
                Контроллер.SendData(Chr(buff[н])); // отправляю посимвольно из буфера  Chr(Код) - функция с VBScript которая преобразует из HEX в символ.
            КонецЦикла;
            Результат = Истина;
        Исключение
        КонецПопытки;
      КонецЕсли;    
    Возврат Результат;    
КонецФункции

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

&НаСервере
Функция ПолучитьОтветНаСервере()
	Результат = "";
	Попытка
		Результат = ПолучитьДанныеСКонтроллера();
		Объект.ОтветКонтроллера = Результат;
		Возврат Истина;
	Исключение
		Возврат ложь;
	КонецПопытки;
КонецФункции

&НаСервере
Функция ПолучитьДанныеСКонтроллера()
	Контроллер = ПолучитьИзВременногоХранилища(ПараметрыСеанса.Z5).Контроллер;
	Ответ = "";
	Пока Истина Цикл
		Результат = "";
		Контроллер.GetData(Результат);
		Если НЕ Результат = "" Тогда
			Ответ = Ответ + Результат;
		Иначе
			//Преобразовать
			БуферПриема = СтрокуВМассивы(Ответ);
			Масс = БуферПриема[0];
			м4 = Неопределено;
			Результат = Преобразовать5_4(Масс,М4);
			Расшифровано = "";
			Для н = 0 По м4.Количество()-1 Цикл
				Расшифровано = Расшифровано + М4[н] + " ";
			КонецЦикла;
			Объект.ОтветКонтроллера = Расшифровано;
			Прервать;
		КонецЕсли;
	КонецЦикла;	
	Возврат Объект.ОтветКонтроллера;
КонецФункции


Так, что мы уже видим, что чтобы отправить команду на контроллер мы должны выполнить следующий код:

Объект.ТипКоманды = "20";
    Объект.Команда = "ПолучитьАдресКонтроллера";
    Объект.ТекстСообщения = "00 08 08 01 00 00 00 00";
    ПодключитьОбработчикОжидания("ВыполнитьКоманду",1);

Дальше все выполнит пара обработчиков ожидания "ВыполнитьКоманду" и "ПолучитьОтвет".

По окончании выполнения команды и получения ответа контроллера будет вызвана процедура ВыполнитьОбработкуОтвета(), которая выполнит требуемые действия с полученным ответом. Не секрет, что некоторые команды зависят от предыдущих. Например, в моем случае для получения всех карт зашитых в контроллер требуется выполнить следующие действия:

1. Запросить адрес последней карты. Выяснить сколько байт занимают все карты, разбить на блоки по 64 байта (1 условный блок хранения в контроллере)

2. Запросить 1 блок

3. Получить ответ - обработать

4. Запросить 2 блок - обработать

........

n. Запросить неполный последний блок

n+1. Обработать.

В этом случае в процедуре ВыполнитьОбработкуОтвета() мы зацикливаем выполнение команд, прямо в этой процедуре запуская на выполнение новую команду.

Функция обработки полученных ответов:

&НаКлиенте
Процедура ВыполнитьОбработкуОтвета()
//    БуферПриема = СтрокуВМассивы(Объект.ОтветКонтроллера);
    Если Объект.Команда = "ПолучитьАдресКонтроллера" Тогда
        М4 = ОтветВМассив();
        ФлагПриема = Истина;
        //Расшифруем полученные данные
        i = 8;
        Пока i < 20 Цикл
            текАдр = АдресКонтроллера(М4[i], i - 8);
            Если ТекАдр.Количество()>0 Тогда
                Для Каждого Эл Из ТекАдр Цикл
                    Объект.СписокКонтроллеров.Добавить(Эл.Значение);
                КонецЦикла;
            КонецЕсли;
            i = i + 1;
        КонецЦикла;
        Объект.Команда = "";
    ИначеЕсли Объект.Команда = "СписокКарт" Тогда
..........................................
    КонецЕсли;
    УправлениеДоступностью(Истина);    
КонецПроцедуры

Почему все так сложно? Дело в том, что SendData() отправляет только когда прекращается активность. Объясню.

Контроллер.sendData("что-то-там");
текВремя  = ТекущаяДата();
Пока Истина Цикл
            Если ТекущаяДата() > текВремя + 10;//Цикл задержки 10 секунд Тогда
                 Прервать;
            КонецЕсли;
КонецЦикла;
Получаем = Контроллер.GetData();

Не работает. Отправка произойдет по окончании выполнения всего кода текущей процедуры, которую мы вызвали, предположим, нажатием на кнопку. Можете проверить.

Итак в заключении.

Предложенный вариант не претендует на оригинальность, но зато работает. Медленно, но работает.

Надеюсь, что мой опыт кому-нибудь пригодится.

Однако, есть мнение. Кому не жалко немного времени, создать ВК с методами:
1. Подключить(Адрес,Порт) Возвращает Истина, Ложь
2. ОтправитьСтроку(Строка) Возвращает Истина Ложь
3. ПрочитатьОтвет() Возвращает ответы, накопленные в буфере Возможен вариант, В какой-либо переменной появляется ответ, который на стороне 1С можно прочитать и/или удалить, если прочитали
4. Отключить 

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

Понимаю, что можно было организовать иначе, но основное требование - минимум изменений. Добавлена в конфигурацию только: переменная Z5 в параметры сеансов.

Если есть что сказать, присоединяйтесь к общению. Я мог что-то упустить. 1С на месте не стоит.

Видео с примером работы с контроллером из 1С.

См. также

Периферийные устройства Системный администратор Программист Платформа 1С v8.3 1С:Розница 2 Россия Абонемент ($m)

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

10 стартмани

14.11.2024    672    3    aximo    0    

3

Периферийные устройства Системный администратор Пользователь Платформа 1С v8.3 1С:Бухгалтерия 3.0 Абонемент ($m)

Простая в использовании обработка https://infostart.ru/1c/tools/1001819/ в целом решает поставленную задачу, но имеет явный недостаток - взаимодействует только с принтерами, подключенными к серверу. Доработанная версия позволяет работать как с принтерами на клиенте, так и на сервере

1 стартмани

30.08.2024    457    3    Sergey1CSpb    0    

4

Периферийные устройства Пользователь Платформа 1С v8.3 1С:Управление торговлей 11 1С:Управление нашей фирмой 3.0 Розничная и сетевая торговля (FMCG) Россия Абонемент ($m)

Расширение для вывода информации для покупателя из РМК на второй монитор. Также реализован вывод картинок из каталога в левую часть экрана покупателя. Разработано для УТ 11.5, УНФ 3.0.6 и 3.0.9.

1 стартмани

12.08.2024    1324    28    Rastopchinss    15    

3

Периферийные устройства Пользователь Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Россия Абонемент ($m)

Вывод для клиента на второй монитор (информационное табло) номера заказа в браузер (по умолчанию, например, Яндекс). Внешняя обработка может быть легко переделана под другие конфигурации (нужды) даже начинающим программистом.

1 стартмани

02.08.2024    770    0    AlOkt    0    

5

Периферийные устройства Программист Пользователь Платформа 1С v8.3 1С:Розница 3.0 Абонемент ($m)

Пример работы с эмулятором дисплея покупателя через библиотеку БПО.

6 стартмани

10.07.2024    807    6    aximo    0    

3

Периферийные устройства Программист Пользователь Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Речь пойдет не о сканерах штрихкодов 2D/3D/RF/распознавании лиц и прочего, а о старом добром аппарате, позволяющем считать страницу и отправить ее образ в ПК через COM/USB порт. Рассмотрим, как можно подключить и использовать сканер в типовых 1С-конфигурациях. И что делать, если никак не найти команду настройки сканера.

1 стартмани

28.05.2024    1174    Sergey1CSpb    2    

7

Периферийные устройства Пользователь Платформа 1С v8.3 1С:Розница 2 Россия Абонемент ($m)

Расширение для 1С: Розница 2.3 версий 2.3.15.ХХХ и выше. Удобный способ изменения принтера по умолчанию во встроенной обработке печати ценников и этикеток. Только для операционной системы Windows.

1 стартмани

13.05.2024    1159    5    independ    0    

5
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. asved.ru 37 11.01.17 10:24 Сейчас в теме
Засунуть COMОбъект в параметры сеанса временное хранилище, да еще по произвольному адресу - это, конечно, сильный ход. И неожиданный.

Вы его еще на клиента передать попробуйте. Или в базу записать.
3. asdfgcom 424 11.01.17 15:22 Сейчас в теме
(1) этот метод как раз рассматривался на инфостарте. Очень выручил. Глобально не получается держать COMобъект, т.к. после выполнения на сервере и повторном входе переменная переинициализируется. В реквизитах объекта держать нельзя. Они доступны клиенту, а COMобъекты не сереализуются. Как тогда? Остается хранилище. Как передать несереализуемый объект? Прячем его в, например, структуру...

(2) попробую.

Только что перепроверил, почему не работал "ДобавитьОбработчик". Заставил работать по событиям.
Где-то накосячил с передачей между клиентом и сервером, что вызывало appCrash 1с.exe
На самом деле все будет гораздо проще.

ДобавитьОбработчик ws.Connect, Connect; 
ДобавитьОбработчик ws.ConnectionRequest, ConnectionRequest; 
ДобавитьОбработчик ws.DataArrival, DataArrival;
ДобавитьОбработчик ws.Error, WinSocketError;

И все взлетело. Избавился от ежесекундных обработчиков.
Статью перепишу на днях.
4. asved.ru 37 11.01.17 17:23 Сейчас в теме
(3) Как вы думаете, что из себя представляет COMОбъект, и что помещается во временное хранилище?
И что Вы достанете из хранилища в следующем вызове, когда следующий вызов будет исполняться на другом сервере кластера, или после перезапуска процесса? Или после разрыва сетевого соединения?

jONES1979; +1 Ответить
5. asdfgcom 424 11.01.17 21:13 Сейчас в теме
(4) Надеюсь, я Вас правильно понял.
В Параметрах сеанса мы держим только строку с адресом временного хранилища в котором лежит наш COMобъект. Методика, описана на волшебном форуме (не уверен, что можно явно ссылаться на сторонние форумы, поэтому поиск) "Хранение COM Объектов на Сервере ТонкогоКлиента Как сохранить COM-объект на Сервере между СервернымиВызовами. Автор статьи: H A D G E H O G s"
На счет другого сервера кластера - не знаю... Но и не надо, надеюсь. Ведь COMобъект в хранилище, адрес и уникальный идентификатор у нас имеется. Всегда поднимем объект.
После разрыва сетевого соединения получим ошибку, переподключимся и сунем обратно адрес на хранилище.
7. asved.ru 37 12.01.17 14:58 Сейчас в теме
(5)
Всегда поднимем объект.


Поднимите объект через 21 минуту неактивности.

Это работает исключительно потому, что сериализация и собственно запись во временное хранилище производится отложенно. Т.е. несериализуемая ссылка на COM-объект находится в кэше рабочего процесса. Как только сервер попытается ее сериализовать - тут-то она и уничтожается.

Другой сервер кластера или клиент при попытке получения значения инициирует его физическую сериализациию, т.к. обращается к сервису сеансовых данных. Т.е. обращение к объекту с другого сервера кластера уничтожит его и на первом сервере.
9. asdfgcom 424 12.01.17 17:57 Сейчас в теме
(7)(8) Приветствую, Антон!
Да, все верно. Однако в моем случае не критично.
Winsocket используется только для связи с оборудованием. Во время обращения к нему соединение не потеряется. Факт. Если COMОбъект теряется из временного хранилища (при простое), то ошибка соединения - переподключение с переинициализацией COMобъекта. Я этого даже не замечал. Для интереса, поставлю точку в отладчике в процедуре переподключения, убедиться, что соединение теряется. Переинициализацию сделал как раз из-за предупреждения в вышепредложенной статье автора H A D G E H O G s:
"ComОбъект теряется на 20 -ой минуте его "неиспользования". Так сделали 1С. Столько живет объект во временном хранилище, если у него нет идентификатора - формы владельца. Лечение просто - раз в 500 секунд - считывать COMОбъект из Временного хранилища".
13. asdfgcom 424 12.01.17 19:39 Сейчас в теме
(1) Антон, прошу прощения за невнимательность.
Вы имели в виду мою неточность в описании, точнее некорректное построение фразы:

"Заметим, что COMобъект мы спрятали в структуру... А если "спрятать" его в структуру, ошибок не будет"

Точнее было бы сказать. ...а если спрятать его в структуру, разместить во временное хранилище, тогда ссылку на временное хранилище мы можем передать в переменную, хранимую в параметрах сеанса для того, чтобы использовать ее и на клиенте, и в серверных вызовах без переинициализации самого объекта.. И т.д. (получилось много букв. Я бы читать не стал с этого места дальше.))))
2. mdl@andi72.ru 11.01.17 10:37 Сейчас в теме
ActiveX в УФ поддерживается, не официально. Делал через реализацию интерфейсов для ie:

GetInterfaceSafetyOptions, SetInterfaceSafetyOptions

ну естественно под win
6. Darklight 33 12.01.17 14:33 Сейчас в теме
Большое списбо за статью, познавательно!
Сам храню COM-объекты через модули повторного использования - тоже ретушируются (без упаковки в структуру; как возвращаемые значения), но есть свои неудобства такого подхода.
Но технология COM - это уже прошлый век.
Что же делать под Linux?
10. asdfgcom 424 12.01.17 18:04 Сейчас в теме
(6) Как говорится, спасибо за спасибо.
Что Вы подразумевали под: "Что же делать под Linux?"
COMобъекты может и устарели, но с ними легко быстро не зная ничего кроме 1С и протокола или описания методов начать работать над задачей.
К данной работе я подходил около месяца. Пытался сначала "врапить" по технологии NET, однако знаний не хватало и времени. По протоколу через winsocket надоумил сам производитель оборудования. Уже через неделю описал все команды, через 3 недели готовый прототип обмена. Сейчас "пилю" интерфейс, засовываю в расширение (для этого и понадобились параметры сеанса). К сожалению придется добавлять регистр сведений, синхронизировать его с данными из контроллера.
11. Darklight 33 12.01.17 18:16 Сейчас в теме
(10)Как работать сокeтами под Linux
12. asdfgcom 424 12.01.17 18:30 Сейчас в теме
(11) 1С у заказчика под Windows. Однако, в свете последних событий и импортозамещения, придется скоро осваивать не только сокеты под Linux.
14. asdfgcom 424 28.01.17 12:23 Сейчас в теме
В данный момент отказались от использования WinSocket и работой с контроллером непосредственно из 1С. 1С работает с контроллером очень медленно. На "слабых" машинах приходится полностью отключать автоматический опрос, т.к. обработчики событий начинают подавать команды не по очереди, а одновременно из-за медленной обработки событий и задач. Создавать кэш команд не хочется, решили всю низкую часть перенести на java.
Однако, для простых запросов вышеописанный способ общения может пригодиться.
15. vdenu 01.03.17 17:21 Сейчас в теме
Спасибо за статью, но вероятно я невнимательно её изучил и так и не понял два вопроса:
1. Каким же образом COM-объект созданный на сервере и затем помещённый в структуре во Временное хранилище может стать доступным на стороне клиента? ПолучитьИзВременногоХранилища() не срабатывает со стандартной ошибкой "Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа" Т.е. программа знает, что в структуре я "спрятал" com
2. Если я создаю Винсокет на стороне сервере, то как использовать ДобавитьОбработчик?
16. asdfgcom 424 01.03.17 19:01 Сейчас в теме
(15)
1. Идя не нова, "Хранение COM Объектов на Сервере ТонкогоКлиента Как сохранить COM-объект на Сервере между СервернымиВызовами. Автор статьи: H A D G E H O G s"

Контроллер = Новый COMОбъект("mswinsock.winsock");
.......

СтруктОбъекта = Новый Структура("Контроллер",Контроллер);
ПараметрыСеанса.Z5=ПоместитьВоВременноеХранилище(СтруктОбъекта,Новый УникальныйИдентификатор());

Помещаем в параметры сеанса, чтобы можно было дотянуться.
(мне нужно было, чтобы можно было использовать и на стороне конфигурации и на стороне расширения.)

2. Второй способ реализован в данный момент.

Следующим сообщением (вставка кода не работает)

17. asdfgcom 424 01.03.17 19:14 Сейчас в теме
Вынес все в клиент. Только в этом случае работают обработчики событий. Объявил переменную Контроллер. Ограничил весь функционал одной обработкой.

Прошу прощения, не работает нормально вставка кода...

&НаКлиенте
Функция ВыполнитьПодключениеККонтроллеру()
	Попытка
		Контроллер = Новый COMОбъект(Объект.AddINКомпоненты); 
		ПараметрыКонтроллера = Новый Структура("Адрес, Порт");
		ПараметрыКонтроллера.Адрес = Объект.АдресПодключения;
		ПараметрыКонтроллера.Порт = Объект.ПортПодключения;
		
		Если Контроллер.State <> 7 тогда
			
			Если Контроллер.State <> 0 Тогда
				Контроллер.Close();
			КонецЕсли;
			
			Контроллер.RemoteHost = СокрЛП(ПараметрыКонтроллера.Адрес);
			Контроллер.RemotePort = СокрЛП(ПараметрыКонтроллера.Порт);
			
			Контроллер.Connect();
		Иначе
			Контроллер.Close();
			
			Контроллер.RemoteHost = СокрЛП(ПараметрыКонтроллера.Адрес);
			//		ws.RemoteHostIP = СокрЛП(ПараметрыПодключения.Адрес);
			Контроллер.RemotePort = СокрЛП(ПараметрыКонтроллера.Порт);
			
			Контроллер.Connect();
		КонецЕсли;
		
		ДобавитьОбработчик Контроллер.Connect, Connect; 
		ДобавитьОбработчик Контроллер.ConnectionRequest, ConnectionRequest; 
		ДобавитьОбработчик Контроллер.DataArrival, DataArrival;
		ДобавитьОбработчик Контроллер.Error, WinSocketError;
		
			Возврат Истина;
	Исключение
		Возврат Ложь;	
	КонецПопытки;
КонецФункции
Показать

Платформа: 8.3.9.1850
18. vdenu 02.03.17 09:29 Сейчас в теме
(17) Да, на клиенте действительно работает, а на сервере технология не живёт и ком-объект в хранилище хранится только для сервера, никакая упаковка не позволяет его получить на клиенте из хранилища, увы. Кстати, спасибо за статью - подтолкнула к экспериментам.
19. asdfgcom 424 02.03.17 11:00 Сейчас в теме
(18) Настойчиво рекомендую почитать: "Хранение COM Объектов на Сервере ТонкогоКлиента Как сохранить COM-объект на Сервере между СервернымиВызовами. Автор статьи: H A D G E H O G s"
20. Bukaska 140 02.03.17 11:16 Сейчас в теме
(17)Да почему.. вставка кода работает. Выделили текст и нажали на значок: </> - и готово
21. asdfgcom 424 02.03.17 14:57 Сейчас в теме
(20) У меня браузер Chrome. Иногда (не всегда) после нажатия на </> не открывается форма вставки кода, а появляется то же окно редактирования сообщения, только без набранного текста. Не разобрался пока в чем дело.
22. vdenu 02.03.17 15:10 Сейчас в теме
Евгений, я недостаточно точно выразился. Вот ваша цитата: "Как же его хранить? Будем хранить его в параметрах сеанса. Оттуда он доступен и клиенту и серверу. " Хранить в структуре его (ComОбъект) можно, но доступен он всегда только для сервера и никогда для клиента. (Соответственно в случае с winsocket подобное решение лишено смысла)
23. asdfgcom 424 02.03.17 18:48 Сейчас в теме
24. Alexoidic 25.04.20 20:06 Сейчас в теме
Здравствуйте!!! Написал TcpClient на 1с, TCPServer написан на си шарпе, Отправка данных работает отлично, не могу получить ответ с сервера, не отрабатывает событие WinSocketDataArrival. Никак не могу понять почему.

#Область ComObject_WinSocket
&НаКлиенте
Процедура InitWinSocketClient()
	Порт = 8888;
	Хост="10.4.1.8"; 
	WinsocketClient = Новый COMObject("mswinsock.winsock");		
	ДобавитьОбработчик  WinsocketClient.Connect, ПриПодключенииКлиентаКCерверу; 
	ДобавитьОбработчик  WinsocketClient.SendProgress, WinSocketSendProgress;
	ДобавитьОбработчик  WinsocketClient.SendComplete, WinSocketSendComplete;
	ДобавитьОбработчик  WinsocketClient.DataArrival, WinSocketDataArrival;
	ДобавитьОбработчик  WinsocketClient.Error, WinSocketError;
	WinsocketClient.RemoteHost = Хост;
	WinsocketClient.RemotePort = Порт;
	Попытка
		WinsocketClient.Connect();
		// само подключение состоится только после выхода из текущего метода
		// после подключения выполнится ПриПодключенииКлиентаКсерверу

		Исключение
	КонецПопытки;
КонецПроцедуры

&НаКлиенте
Процедура WinSocketSendProgress(bytesSent, bytesRemaining)
	Состояние("Передача списка",(bytesSent+bytesRemaining)/bytesSent*100);
КонецПроцедуры

&НаКлиенте
Процедура WinSocketSendComplete()
	
	Сообщить(Строка(ТекущаяДата()) + " | Отправка данных завершена!!! ");

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

&НаКлиенте
Процедура WinSocketError(Number, Description, Scode, Source, HelpFile,HelpContext, CancelDisplay)

    Сообщить("Ошибка передачи:"+ Description);

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

&НаКлиенте
Процедура WinSocketDataArrival(bytesTotal)

	ТкстСообщения = ""; 
			WinsocketClient.GetData(ТкстСообщения, bytesTotal);
    Сообщить(ТкстСообщения);

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

&НаКлиенте
Процедура ПриПодключенииКлиентаКCерверу() Экспорт
	//КодДляПередачи=686;
//	Если ЗначениеЗаполнено(ЗаписьJSON) Тогда
		WinsocketClient.SendData(ЗаписьJSON.Закрыть());
//	КонецЕсли;
	УдалитьОбработчик WinsocketClient.Connect, ПриПодключенииКлиентаКCерверу; 
КонецПроцедуры
#КонецОбласти
Показать
25. ssfedkin 6 18.08.21 16:20 Сейчас в теме
(24) Не могу понять где хранится WinsocketClient?
26. basilio58 20.08.21 16:13 Сейчас в теме
Здравствуйте. Ваша публикация 2017 года. Что изменилось с тех пор? Мне нужно обеспечить передачу заданий на печать в промышленный принтер по TCP/IP. Для "Честного знака". Как это лучше организовать из 1с?
27. kozusenok 54 10.09.21 09:22 Сейчас в теме
Добрый день. Кто-нибудь задавался вопросом как на Winsock сделать сервер для работы с несколькими клиентами одновременно/параллельно?
Оставьте свое сообщение