Пример реализации обмена с оборудованием через winsocket на управляемых формах по протоколу TCP
Комментарии
В избранное
Подписаться на ответы
Сортировка:
Древо развёрнутое
Свернуть все
(1) этот метод как раз рассматривался на инфостарте. Очень выручил. Глобально не получается держать COMобъект, т.к. после выполнения на сервере и повторном входе переменная переинициализируется. В реквизитах объекта держать нельзя. Они доступны клиенту, а COMобъекты не сереализуются. Как тогда? Остается хранилище. Как передать несереализуемый объект? Прячем его в, например, структуру...
(2) попробую.
Только что перепроверил, почему не работал "ДобавитьОбработчик". Заставил работать по событиям.
Где-то накосячил с передачей между клиентом и сервером, что вызывало appCrash 1с.exe
На самом деле все будет гораздо проще.
И все взлетело. Избавился от ежесекундных обработчиков.
Статью перепишу на днях.
(2) попробую.
Только что перепроверил, почему не работал "ДобавитьОбработчик". Заставил работать по событиям.
Где-то накосячил с передачей между клиентом и сервером, что вызывало appCrash 1с.exe
На самом деле все будет гораздо проще.
ДобавитьОбработчик ws.Connect, Connect;
ДобавитьОбработчик ws.ConnectionRequest, ConnectionRequest;
ДобавитьОбработчик ws.DataArrival, DataArrival;
ДобавитьОбработчик ws.Error, WinSocketError;
И все взлетело. Избавился от ежесекундных обработчиков.
Статью перепишу на днях.
(3) Как вы думаете, что из себя представляет COMОбъект, и что помещается во временное хранилище?
И что Вы достанете из хранилища в следующем вызове, когда следующий вызов будет исполняться на другом сервере кластера, или после перезапуска процесса? Или после разрыва сетевого соединения?
И что Вы достанете из хранилища в следующем вызове, когда следующий вызов будет исполняться на другом сервере кластера, или после перезапуска процесса? Или после разрыва сетевого соединения?
(4) Надеюсь, я Вас правильно понял.
В Параметрах сеанса мы держим только строку с адресом временного хранилища в котором лежит наш COMобъект. Методика, описана на волшебном форуме (не уверен, что можно явно ссылаться на сторонние форумы, поэтому поиск) "Хранение COM Объектов на Сервере ТонкогоКлиента Как сохранить COM-объект на Сервере между СервернымиВызовами. Автор статьи: H A D G E H O G s"
На счет другого сервера кластера - не знаю... Но и не надо, надеюсь. Ведь COMобъект в хранилище, адрес и уникальный идентификатор у нас имеется. Всегда поднимем объект.
После разрыва сетевого соединения получим ошибку, переподключимся и сунем обратно адрес на хранилище.
В Параметрах сеанса мы держим только строку с адресом временного хранилища в котором лежит наш COMобъект. Методика, описана на волшебном форуме (не уверен, что можно явно ссылаться на сторонние форумы, поэтому поиск) "Хранение COM Объектов на Сервере ТонкогоКлиента Как сохранить COM-объект на Сервере между СервернымиВызовами. Автор статьи: H A D G E H O G s"
На счет другого сервера кластера - не знаю... Но и не надо, надеюсь. Ведь COMобъект в хранилище, адрес и уникальный идентификатор у нас имеется. Всегда поднимем объект.
После разрыва сетевого соединения получим ошибку, переподключимся и сунем обратно адрес на хранилище.
(5)
Поднимите объект через 21 минуту неактивности.
Это работает исключительно потому, что сериализация и собственно запись во временное хранилище производится отложенно. Т.е. несериализуемая ссылка на COM-объект находится в кэше рабочего процесса. Как только сервер попытается ее сериализовать - тут-то она и уничтожается.
Другой сервер кластера или клиент при попытке получения значения инициирует его физическую сериализациию, т.к. обращается к сервису сеансовых данных. Т.е. обращение к объекту с другого сервера кластера уничтожит его и на первом сервере.
Всегда поднимем объект.
Поднимите объект через 21 минуту неактивности.
Это работает исключительно потому, что сериализация и собственно запись во временное хранилище производится отложенно. Т.е. несериализуемая ссылка на COM-объект находится в кэше рабочего процесса. Как только сервер попытается ее сериализовать - тут-то она и уничтожается.
Другой сервер кластера или клиент при попытке получения значения инициирует его физическую сериализациию, т.к. обращается к сервису сеансовых данных. Т.е. обращение к объекту с другого сервера кластера уничтожит его и на первом сервере.
(7)(8) Приветствую, Антон!
Да, все верно. Однако в моем случае не критично.
Winsocket используется только для связи с оборудованием. Во время обращения к нему соединение не потеряется. Факт. Если COMОбъект теряется из временного хранилища (при простое), то ошибка соединения - переподключение с переинициализацией COMобъекта. Я этого даже не замечал. Для интереса, поставлю точку в отладчике в процедуре переподключения, убедиться, что соединение теряется. Переинициализацию сделал как раз из-за предупреждения в вышепредложенной статье автора H A D G E H O G s:
"ComОбъект теряется на 20 -ой минуте его "неиспользования". Так сделали 1С. Столько живет объект во временном хранилище, если у него нет идентификатора - формы владельца. Лечение просто - раз в 500 секунд - считывать COMОбъект из Временного хранилища".
Да, все верно. Однако в моем случае не критично.
Winsocket используется только для связи с оборудованием. Во время обращения к нему соединение не потеряется. Факт. Если COMОбъект теряется из временного хранилища (при простое), то ошибка соединения - переподключение с переинициализацией COMобъекта. Я этого даже не замечал. Для интереса, поставлю точку в отладчике в процедуре переподключения, убедиться, что соединение теряется. Переинициализацию сделал как раз из-за предупреждения в вышепредложенной статье автора H A D G E H O G s:
"ComОбъект теряется на 20 -ой минуте его "неиспользования". Так сделали 1С. Столько живет объект во временном хранилище, если у него нет идентификатора - формы владельца. Лечение просто - раз в 500 секунд - считывать COMОбъект из Временного хранилища".
(1) Антон, прошу прощения за невнимательность.
Вы имели в виду мою неточность в описании, точнее некорректное построение фразы:
"Заметим, что COMобъект мы спрятали в структуру... А если "спрятать" его в структуру, ошибок не будет"
Точнее было бы сказать. ...а если спрятать его в структуру, разместить во временное хранилище, тогда ссылку на временное хранилище мы можем передать в переменную, хранимую в параметрах сеанса для того, чтобы использовать ее и на клиенте, и в серверных вызовах без переинициализации самого объекта.. И т.д. (получилось много букв. Я бы читать не стал с этого места дальше.))))
Вы имели в виду мою неточность в описании, точнее некорректное построение фразы:
"Заметим, что COMобъект мы спрятали в структуру... А если "спрятать" его в структуру, ошибок не будет"
Точнее было бы сказать. ...а если спрятать его в структуру, разместить во временное хранилище, тогда ссылку на временное хранилище мы можем передать в переменную, хранимую в параметрах сеанса для того, чтобы использовать ее и на клиенте, и в серверных вызовах без переинициализации самого объекта.. И т.д. (получилось много букв. Я бы читать не стал с этого места дальше.))))
Большое списбо за статью, познавательно!
Сам храню COM-объекты через модули повторного использования - тоже ретушируются (без упаковки в структуру; как возвращаемые значения), но есть свои неудобства такого подхода.
Но технология COM - это уже прошлый век.
Что же делать под Linux?
Сам храню COM-объекты через модули повторного использования - тоже ретушируются (без упаковки в структуру; как возвращаемые значения), но есть свои неудобства такого подхода.
Но технология COM - это уже прошлый век.
Что же делать под Linux?
(6) Как говорится, спасибо за спасибо.
Что Вы подразумевали под: "Что же делать под Linux?"
COMобъекты может и устарели, но с ними легко быстро не зная ничего кроме 1С и протокола или описания методов начать работать над задачей.
К данной работе я подходил около месяца. Пытался сначала "врапить" по технологии NET, однако знаний не хватало и времени. По протоколу через winsocket надоумил сам производитель оборудования. Уже через неделю описал все команды, через 3 недели готовый прототип обмена. Сейчас "пилю" интерфейс, засовываю в расширение (для этого и понадобились параметры сеанса). К сожалению придется добавлять регистр сведений, синхронизировать его с данными из контроллера.
Что Вы подразумевали под: "Что же делать под Linux?"
COMобъекты может и устарели, но с ними легко быстро не зная ничего кроме 1С и протокола или описания методов начать работать над задачей.
К данной работе я подходил около месяца. Пытался сначала "врапить" по технологии NET, однако знаний не хватало и времени. По протоколу через winsocket надоумил сам производитель оборудования. Уже через неделю описал все команды, через 3 недели готовый прототип обмена. Сейчас "пилю" интерфейс, засовываю в расширение (для этого и понадобились параметры сеанса). К сожалению придется добавлять регистр сведений, синхронизировать его с данными из контроллера.
В данный момент отказались от использования WinSocket и работой с контроллером непосредственно из 1С. 1С работает с контроллером очень медленно. На "слабых" машинах приходится полностью отключать автоматический опрос, т.к. обработчики событий начинают подавать команды не по очереди, а одновременно из-за медленной обработки событий и задач. Создавать кэш команд не хочется, решили всю низкую часть перенести на java.
Однако, для простых запросов вышеописанный способ общения может пригодиться.
Однако, для простых запросов вышеописанный способ общения может пригодиться.
Спасибо за статью, но вероятно я невнимательно её изучил и так и не понял два вопроса:
1. Каким же образом COM-объект созданный на сервере и затем помещённый в структуре во Временное хранилище может стать доступным на стороне клиента? ПолучитьИзВременногоХранилища() не срабатывает со стандартной ошибкой "Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа" Т.е. программа знает, что в структуре я "спрятал" com
2. Если я создаю Винсокет на стороне сервере, то как использовать ДобавитьОбработчик?
1. Каким же образом COM-объект созданный на сервере и затем помещённый в структуре во Временное хранилище может стать доступным на стороне клиента? ПолучитьИзВременногоХранилища() не срабатывает со стандартной ошибкой "Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа" Т.е. программа знает, что в структуре я "спрятал" com
2. Если я создаю Винсокет на стороне сервере, то как использовать ДобавитьОбработчик?
(15)
1. Идя не нова, "Хранение COM Объектов на Сервере ТонкогоКлиента Как сохранить COM-объект на Сервере между СервернымиВызовами. Автор статьи: H A D G E H O G s"
Контроллер = Новый COMОбъект("mswinsock.winsock");
.......
СтруктОбъекта = Новый Структура("Контроллер",Контроллер);
ПараметрыСеанса.Z5=ПоместитьВоВременноеХранилище(СтруктОбъекта,Новый УникальныйИдентификатор());
Помещаем в параметры сеанса, чтобы можно было дотянуться.
(мне нужно было, чтобы можно было использовать и на стороне конфигурации и на стороне расширения.)
2. Второй способ реализован в данный момент.
Следующим сообщением (вставка кода не работает)
1. Идя не нова, "Хранение COM Объектов на Сервере ТонкогоКлиента Как сохранить COM-объект на Сервере между СервернымиВызовами. Автор статьи: H A D G E H O G s"
Контроллер = Новый COMОбъект("mswinsock.winsock");
.......
СтруктОбъекта = Новый Структура("Контроллер",Контроллер);
ПараметрыСеанса.Z5=ПоместитьВоВременноеХранилище(СтруктОбъекта,Новый УникальныйИдентификатор());
Помещаем в параметры сеанса, чтобы можно было дотянуться.
(мне нужно было, чтобы можно было использовать и на стороне конфигурации и на стороне расширения.)
2. Второй способ реализован в данный момент.
Следующим сообщением (вставка кода не работает)
Вынес все в клиент. Только в этом случае работают обработчики событий. Объявил переменную Контроллер. Ограничил весь функционал одной обработкой.
Прошу прощения, не работает нормально вставка кода...
Платформа: 8.3.9.1850
Прошу прощения, не работает нормально вставка кода...
&НаКлиенте
Функция ВыполнитьПодключениеККонтроллеру()
Попытка
Контроллер = Новый 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
(17) Да, на клиенте действительно работает, а на сервере технология не живёт и ком-объект в хранилище хранится только для сервера, никакая упаковка не позволяет его получить на клиенте из хранилища, увы. Кстати, спасибо за статью - подтолкнула к экспериментам.
Евгений, я недостаточно точно выразился. Вот ваша цитата: "Как же его хранить? Будем хранить его в параметрах сеанса. Оттуда он доступен и клиенту и серверу. " Хранить в структуре его (ComОбъект) можно, но доступен он всегда только для сервера и никогда для клиента. (Соответственно в случае с winsocket подобное решение лишено смысла)
Здравствуйте!!! Написал 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ерверу;
КонецПроцедуры
#КонецОбласти
ПоказатьВопросы с вознаграждением
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|