Пример реализации обмена с оборудованием через 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С.

См. также

Распознавание номеров автомашин с ip - камер, видео, фото

Распознавание документов и образов Периферийные устройства Автомобили, автосервисы Россия Платные (руб)

Программа считывает кадры с ip-камер (http - запрос к камере), видео, фото (источники кадров (нет ограничения на их количество) настраивается в конфигурационном файле), находит и распознает номера автомашин и сохраняет в базу db, с сохранением фото номера и автомашины, а также времени детекции.

20400 руб.

31.05.2023    3943    3    1    

4

Тернистый путь к физической клавиатуре для программиста 1С

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

Долгое время я активно пользовался различными хоткеерами, шаблонами текста, специальными раскладками клавиатуры. Я из тех, кто очень долго верил в Снегопат... Так сложилось, что на моем текущем месте работы довольно строгая политика информационной безопасности, а потому со всем привычным софтом, который делал жизнь проще, мне пришлось расстаться. И даже шаблоны кода при каждом терминальном подключении требуется настраивать в конфигураторе заново. Как известно, если какую-то задачу нельзя решить на стороне софта, то стоит поискать железное решение.

1 стартмани

вчера в 11:00    3346    madonov    35    

26

[История разработки] Управляем промышленным принтером EBS-1500 из 1С

Периферийные устройства Платформа 1С v8.3 Бесплатно (free)

«У нас было два контроллера Huidu, семьдесят две китайские монохромные панели на светоизлучающих диодах, они же LED, четыре мегабайта flash памяти, 1С и целое море поддерживаемых форматов вывода информации - текстов, картинок, анимаций, а так же литр промывочной жидкости, литр разбавителя, ящик черных чернил, и 12 патч-кордов и различных удлинителей. Не то, чтобы всё это было категорически необходимо в маркировке, но если уж начал собирать маркиратор на 1С, то к делу надо подходить серьёзно.» - Страх и ненависть в Маркировке, 2019 г.

01.04.2024    1219    Interrupted    14    

34

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

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

Внешняя обработка получения изображения с веб-камеры с возможностью его кадрирования по произвольно выделенной области. Использует собственную внешнюю компоненту на основе библиотеки AForge. Содержит примеры интерактивного взаимодействия с полем HTML.

20.03.2024    394    1    AndSem    1    

4

Прямая печать на принтерах TSC из 1С

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

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

1 стартмани

19.02.2024    618    5    realslavyan    0    

5

HotKeys на Python для 1С

Периферийные устройства Конфигурации 1cv8 Бесплатно (free)

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

20.12.2023    5332    John_d    26    

74

Очистка очереди печати конкретного принтера

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

Очистка очереди печати выбранного принтера, перезапуск службы печати, вывод списка системных принтеров, открытие свойств принтера из 1С.

1 стартмани

07.11.2023    1305    2    vsnazarov    1    

26

Печать этикеток на DYMO LabelManager 280 через DYMO Connect Web Service

Периферийные устройства WEB-интеграция Этикетки, ценники Платформа 1С v8.3 Конфигурации 1cv8 Россия Бесплатно (free)

На сайте производителя принтера DYMO LabelManager 280 вместе с драйвером поставляется пакет DYMO Connect, который предлагает функционал вёрстки этикеток в фирменном формате и отправки их напрямую на принтер. Так же в этом пакете есть веб-сервис для взаимодействия с принтером через HTTP-запросы, о котором и пойдет речь в этой статье.

29.08.2023    1543    GeraltSnow    0    

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

Вы его еще на клиента передать попробуйте. Или в базу записать.
3. asdfgcom 415 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 36 11.01.17 17:23 Сейчас в теме
(3) Как вы думаете, что из себя представляет COMОбъект, и что помещается во временное хранилище?
И что Вы достанете из хранилища в следующем вызове, когда следующий вызов будет исполняться на другом сервере кластера, или после перезапуска процесса? Или после разрыва сетевого соединения?

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


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

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

Другой сервер кластера или клиент при попытке получения значения инициирует его физическую сериализациию, т.к. обращается к сервису сеансовых данных. Т.е. обращение к объекту с другого сервера кластера уничтожит его и на первом сервере.
9. asdfgcom 415 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 415 12.01.17 19:39 Сейчас в теме
(1) Антон, прошу прощения за невнимательность.
Вы имели в виду мою неточность в описании, точнее некорректное построение фразы:

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

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

GetInterfaceSafetyOptions, SetInterfaceSafetyOptions

ну естественно под win
6. Darklight 32 12.01.17 14:33 Сейчас в теме
Большое списбо за статью, познавательно!
Сам храню COM-объекты через модули повторного использования - тоже ретушируются (без упаковки в структуру; как возвращаемые значения), но есть свои неудобства такого подхода.
Но технология COM - это уже прошлый век.
Что же делать под Linux?
10. asdfgcom 415 12.01.17 18:04 Сейчас в теме
(6) Как говорится, спасибо за спасибо.
Что Вы подразумевали под: "Что же делать под Linux?"
COMобъекты может и устарели, но с ними легко быстро не зная ничего кроме 1С и протокола или описания методов начать работать над задачей.
К данной работе я подходил около месяца. Пытался сначала "врапить" по технологии NET, однако знаний не хватало и времени. По протоколу через winsocket надоумил сам производитель оборудования. Уже через неделю описал все команды, через 3 недели готовый прототип обмена. Сейчас "пилю" интерфейс, засовываю в расширение (для этого и понадобились параметры сеанса). К сожалению придется добавлять регистр сведений, синхронизировать его с данными из контроллера.
11. Darklight 32 12.01.17 18:16 Сейчас в теме
(10)Как работать сокeтами под Linux
12. asdfgcom 415 12.01.17 18:30 Сейчас в теме
(11) 1С у заказчика под Windows. Однако, в свете последних событий и импортозамещения, придется скоро осваивать не только сокеты под Linux.
14. asdfgcom 415 28.01.17 12:23 Сейчас в теме
В данный момент отказались от использования WinSocket и работой с контроллером непосредственно из 1С. 1С работает с контроллером очень медленно. На "слабых" машинах приходится полностью отключать автоматический опрос, т.к. обработчики событий начинают подавать команды не по очереди, а одновременно из-за медленной обработки событий и задач. Создавать кэш команд не хочется, решили всю низкую часть перенести на java.
Однако, для простых запросов вышеописанный способ общения может пригодиться.
15. vdenu 01.03.17 17:21 Сейчас в теме
Спасибо за статью, но вероятно я невнимательно её изучил и так и не понял два вопроса:
1. Каким же образом COM-объект созданный на сервере и затем помещённый в структуре во Временное хранилище может стать доступным на стороне клиента? ПолучитьИзВременногоХранилища() не срабатывает со стандартной ошибкой "Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа" Т.е. программа знает, что в структуре я "спрятал" com
2. Если я создаю Винсокет на стороне сервере, то как использовать ДобавитьОбработчик?
16. asdfgcom 415 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 415 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 415 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 415 02.03.17 14:57 Сейчас в теме
(20) У меня браузер Chrome. Иногда (не всегда) после нажатия на </> не открывается форма вставки кода, а появляется то же окно редактирования сообщения, только без набранного текста. Не разобрался пока в чем дело.
22. vdenu 02.03.17 15:10 Сейчас в теме
Евгений, я недостаточно точно выразился. Вот ваша цитата: "Как же его хранить? Будем хранить его в параметрах сеанса. Оттуда он доступен и клиенту и серверу. " Хранить в структуре его (ComОбъект) можно, но доступен он всегда только для сервера и никогда для клиента. (Соответственно в случае с winsocket подобное решение лишено смысла)
23. asdfgcom 415 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 52 10.09.21 09:22 Сейчас в теме
Добрый день. Кто-нибудь задавался вопросом как на Winsock сделать сервер для работы с несколькими клиентами одновременно/параллельно?
Оставьте свое сообщение