Russian Qt Forum
Ноябрь 23, 2024, 15:38 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Ожидание данных в асинхронном режиме  (Прочитано 9897 раз)
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« : Июнь 17, 2014, 10:06 »

Коллеги, подскажите, пожалуйста, как организуется ожидание данных в асинхронном режиме?
Задача - взаимодействие по типу запрос/ответ с устройством (контроллером) через сокет. Есть функция, которая выполняет передачу запроса в сокет (функция запроса). Чтение ответа от контроллера выполняется асинхронно, по сигналу readyRead (обработчик ответа).
Мне нужно в функции запроса дождаться ответа железяки, прочесть его и отправить куда надо. Т.е. в функции нужно организовать ожидание и фиксацию завершения работы обработчика ответа. Как передать данные - отдельный вопрос, и речь не о нем.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Bepec
Гость
« Ответ #1 : Июнь 17, 2014, 11:00 »

Так может вам синхронный режим нужен?
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #2 : Июнь 17, 2014, 11:09 »

Нет. Режим многопользовательский, время ответа у разных устройств - разное. Поэтому, пока я жду своего ответа, другие клиенты могут получить свои.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Bepec
Гость
« Ответ #3 : Июнь 17, 2014, 11:40 »

Стоп.

Вы уж определитесь - в функции запроса дождаться ответа железяки. И как вы в этот момент примите другие кадры? насколько я понимаю вы из ф-ции выходить не хотите, потому никак, скорее всего Улыбающийся

Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Июнь 17, 2014, 12:02 »

Ну хотя бы повиснуть на мутексе (а может еще лучше на семафоре), который асинхронка откроет. Или я чего-то не понял в вопросе 
Записан
Hellraiser
Бывалый
*****
Offline Offline

Сообщений: 451


Просмотр профиля
« Ответ #5 : Июнь 17, 2014, 12:34 »

После отправки запроса запускаем разовый сторожевой таймер. Время ожидания должно определяться в протоколе обмена с контроллером. Сработал таймер - значит контроллер не ответил за заданное время, ответил контроллер до срабатывания - останавливаем таймер (если есть объект) или ставим флаг игнорирования (для статического QTimer::singleShot), который обрабатываем в слоте таймера. Только при приеме данных надо помнить о том, что данные могут приходить порциями, т.е. остановка таймера только после чтения полного ответа.
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #6 : Июнь 17, 2014, 13:14 »

Вы уж определитесь - в функции запроса дождаться ответа железяки. И как вы в этот момент примите другие кадры? насколько я понимаю вы из ф-ции выходить не хотите, потому никак, скорее всего Улыбающийся
Собственно, чего темнить - обмен по modbus TCP. Задумка была такая - запросы клиенты передают запросы каждый в своем порожденном процессе. Т.е., подключился к контроллеру, передал, отключился. И ждет некоторое время.
А все ответы получает основной процесс по 502-му порту и складывает в кучку, например, в БД. Вот клиентский процесс должен подождать, когда его ответ появится и забрать.
Возможно, я ошибаюсь - хотел потом проверить. Контроллер можно настроить на любой порт, но сервер всегда должен слушать 502-й. Вот это я и хотел использовать.
Есть, конечно, другое решение - два последовательных запроса (передача запроса, потом получение ответа).
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
qate
Супер
******
Offline Offline

Сообщений: 1177


Просмотр профиля
« Ответ #7 : Июнь 17, 2014, 14:54 »

Собственно, чего темнить - обмен по modbus TCP.

читай спецификацию modbus TCP, может так и невозможно сделать
Записан
Hellraiser
Бывалый
*****
Offline Offline

Сообщений: 451


Просмотр профиля
« Ответ #8 : Июнь 17, 2014, 15:15 »

С контроллером (железякой) должен общаться только программный сервер в режиме "Master-Slave", причем мастер - это сервер. Он же по сети принимает запросы от всех клиентов и формирует очередь запросов к контроллеру. После исполнения запроса контроллером происходит анализ ответа и определение клиента, пославшего этот запрос. И только этому клиенту отправляется ответ (или уведомление о таймауте его запроса). Железяка все-равно не будет исполнять запросы параллельно.
Записан
Hellraiser
Бывалый
*****
Offline Offline

Сообщений: 451


Просмотр профиля
« Ответ #9 : Июнь 17, 2014, 15:19 »

Складывать запросы от клиентов в БД - очень плохая идея. Выполненный запрос никому уже не нужен, следовательно БД будет постоянно модифицироваться и времени на дисковые операции ох как много уйдет. Гораздо эффективнее использовать что-то типа QQueue<QByteArray> с контролем размерности. К примеру, ограничить на 1000 элементов, а при достижении потолка тормозить клиентов.
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #10 : Июнь 17, 2014, 16:48 »

читай спецификацию modbus TCP, может так и невозможно сделать
Может и нельзя.
Цитировать
The listening TCP port 502 is reserved for MODBUS communications. It is mandatory to listen by default on that port. However, some markets or applications might require that another port is dedicated to MODBUS over TCP. For that reason, it is highly recommended that the clients and the servers give the possibility to the user to parameterize the MODBUS over TCP port number. It is important to note that even if another TCP server port is configured for MODBUS service in certain applications, TCP server port 502 must still be available in addition to any application specific ports.
А я разве задавал вопрос о том, можно ли так сделать? Контроллеры бываю разные...
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #11 : Июнь 17, 2014, 17:01 »

После исполнения запроса контроллером происходит анализ ответа и определение клиента, пославшего этот запрос. И только этому клиенту отправляется ответ (или уведомление о таймауте его запроса).
Немного не так. Контроллер тупо транслирует запрос в сеть RS-485. То устройство, которому он адресован, его исполняет и отвечает в соответствии с спецификацией функции. Контроллер просто передает ответ обратно в сеть TCP/IP.
Какому клиенту передать ответ, решает сервер - запрос и ответ имеют для этого идентификатор транзакции. Собственно, мой вопрос и касался того, как мне лучше замкнуть транзакцию.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #12 : Июнь 17, 2014, 17:43 »

Складывать запросы от клиентов в БД - очень плохая идея. Выполненный запрос никому уже не нужен...
Почему же не нужен? Ответы на запросы определенного типа (например, получить состояние устройства) очень даже нужны - они описывают текущее состояние системы.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Hellraiser
Бывалый
*****
Offline Offline

Сообщений: 451


Просмотр профиля
« Ответ #13 : Июнь 17, 2014, 18:44 »

Результат выполнения запроса нужен, но только результат, а не сам запрос. Для модбаса запрос - номера функции или регистров устройства, зачем хранить этот байтовый набор? А вот результат, описывающий состояние системы, - однозначно нужен. А 485 интерфейс вообще полудуплексный - одновременно болтать и слушать не получится.
Записан
Bepec
Гость
« Ответ #14 : Июнь 17, 2014, 19:35 »

Если у вас RS485, то у вас должно быть временное окно для кадра. Значение, при котором устройство считается недоступным. И у вас получается синхронная работа, ведь RS485, как правильно замечено, может обеспечивать одномоментную передачу лишь одного кадра.

Не вижу проблемы. У меня был тупо QEventLoop c таймером в 500 мс. Если за 500 мс не пришёл ответ - следующий запрос, текущее устройство недоступно.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.083 секунд. Запросов: 22.