![]() |
|
|
![]()
|
|
| xbarmaglot |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 149 Регистрация: 28.8.2012 Репутация: нет Всего: нет |
Класс QIODevice работает асинхронно: есть write и слот readyRead.
Но, помимо этого, есть методы waitForBytesWritten и waitForReadyRead, которые позволяют сделать работу синхронной. Как можно реализовать данный механизм на собственном объекте? З.Ы. Идея в том, что есть TCP поток, через который передаются данные различного типа. Это команды, которые ходят одну и другую сторону. На некоторые команды нужно отвечать, а на некоторые нет. То есть некоторые синхронные, а некоторые асинхронные. С асинхронными все понятно, а вот с синхронными проблема. Нужно на посланный запрос получить ответ, который может быть замешан с асинхронными ответами. Как быть в данном случае ? |
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 24 Всего: 196 |
xbarmaglot, я не очень понимаю, что тебя затрудняет? Данные в любом случае отправляются в том порядке, в каком ты записываешь. Если ты не будешь работать с классом из нескольких потоков, то проблем у тебя быть не должно. Тупо реагируй на сигнал readyRead. Если же тебе необходимо отправлять асинхронные данные, а периодически синхронно отвечать, то, опять же, проблем быть не должно. Другое дело, что если твой протокол подразумевает, что после синхронной команды не может придти ничего, кроме синхронного ответа, то проблема не в классе, а в протоколе.
|
|||
|
||||
| xbarmaglot |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 149 Регистрация: 28.8.2012 Репутация: нет Всего: нет |
после синхронной команды может прийти не ответ на него, а асинхронные данные, например. Просто со стороны сервера тоже могут идти асинхронные данные. |
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 24 Всего: 196 |
xbarmaglot, в данный момент не очень понятно, что вызывает у тебя затруднения.
|
|||
|
||||
| xbarmaglot |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 149 Регистрация: 28.8.2012 Репутация: нет Всего: нет |
смысл в том, что клиент, подключаясь к серверу, может ему передавать как асинхронные данные, так и синхронные. на синхронные он должен дождаться ответа с результатом. сложность в том, что сервер помимо ответов может сам слать асинхронные данные. так вот получается, что когда клиент посылает синхронную команду, то в ответ может прийти не результат выполнения команды, а асинхронные данные. вот и возникает вопрос-как реализовать ожидание результата синхронного запроса? |
|||
|
||||
| Guinness |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 310 Регистрация: 21.6.2009 Где: Зеленоград Репутация: 2 Всего: 10 |
А может Вам по другому протокол реализовать? Чтобы не было этой путаницы с синхронными и несинхронными данными?
А в readyRead обрабатывать данные по некоему идентификатору, который бы различал данные по их важности? |
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 24 Всего: 196 |
xbarmaglot, все. Я понял тебя. Это очень легко решается (причем, более корректно, чем ты планировал) следующим образом: когда отправляешь синхронную команду, то ставишь флажок и код команды. Когда приходит на нее ответ обрабатываешь его, снимаешь флажок, отправляешь отложенные асинхронные команды. При отправке асинхронной команды ты проверяешь флажок, если взведен, то помещаешь в очередь отложенных, иначе сразу отправляешь. Обработка ответов вообще единообразна - по сигналу readyRead читаешь и нужным образом реагируешь.
|
|||
|
||||
| xbarmaglot |
|
||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 149 Регистрация: 28.8.2012 Репутация: нет Всего: нет |
у меня есть ID и тип пакета, по которому я могу понять запрос это или ответ. т.к. я использую один сокет для отправки, то я вообще могу синхронизировать отправку данных со стороны клиента. То есть если идет синхронный запрос, то асинхронный не отправляется в данный момент. Со стороны сервера аналогично - если я получил синхронный запрос, то не отправляю асинхронные данные пока не отвечу на него. Но проблема в том, что клиент и сервер не синхронизированы. Допустим клиент начинает синхронный запрос. Он отправляет данные на сокет. И начинает ждать ответа. Отправка - это просто копирование в буфер сокета как только он послал, то сервер, не зная этого (еще не получив запроса) пуляет данные. А потом получает запрос на выполнение синхронной операции. Получается, что клиент в ответ получит не результат выполнения, а асинхронные данные. З.Ы. Вся сложность в том, что клиент работает не по принципу запрос-ответ, а в том, что сервер сам может инициировать передачу асинхронных данных. Правда инициатором синхронных запросов может быть только клиент.
Так чтение в другом методе. В чем тут синхронность ? вот пример
а раз посылаю данные в дном методе, а читаю в другом, то тут я и не могу понять как реализовать синхронную операцию. Или я что-то не понял ? |
||||
|
|||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 24 Всего: 196 |
ты логику не понимаешь. надо делать программу event-based. Т.е. ты обрабатываешь события, а не ждешь данные.
т.е. ты пульнул данные серверу и делаешь все что угодно (не ждешь ответ). Когда сервер пришлет ответ, то у тебя возникнет событие onReadyRead(). Отлично, в его обработчике ты делаешь необходимые операции и опять возвращаешься к "все что угодно". Просто современные gui-приложения в принципе очень сложно сделать синхронными (т.е. что-то сделал, ждешь результат, опять что-то сделал, ждешь результат... - не прокатит). Там после любой реакции на внешние раздражители (пользователь, таймеры, данные из сокетов или другие события) программа должна вернуть управление системе. В случае Qt надо просто завершить функцию-слот. |
|||
|
||||
| xbarmaglot |
|
||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 149 Регистрация: 28.8.2012 Репутация: нет Всего: нет |
bsa, я понимаю, что в идеале алгоритм должен быть полностью асинхронным. Тогда и проблем не будет.
Просто я не совсем понимаю как это сделать. Например, сейчас логика следующая: в отдельном потоке выполняются как синхронные, так асинхронные команды. Для асинхронных команд есть очередь ответов. Я просто после отправки ожидаю на очереди ответ. Получается, что я все-равно пытаюсь сделать все методы синхронными. Последовательность действий алгоритма должна быть четко последовательной. Если не проходит како-либо вызов, то дальнейшее выполнение алгоритма бессмысленно. Если же реагировать на события в слоте, то это очень сложно. Да и слот не может знать что делать с пакетом определенного типа. Это может знать лишь объект, посылающий запрос. Может тут нужно автомат строить ? Только как быть с таймаутами на выполнение операций алгоритма ? Добавлено @ 21:26 P.S. Вот простой пример: пусть для реализации алгоритма необходимо последовательно выполнить 3 команды. Если делать все синхронно, то
Если все делать асинхронно, то
как-то так... А если методов десятки? Или как-то проще через слоты можно обработать ? Это сообщение отредактировал(а) xbarmaglot - 7.6.2013, 21:28 |
||||
|
|||||
| Guinness |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 310 Регистрация: 21.6.2009 Где: Зеленоград Репутация: 2 Всего: 10 |
Ну да, для этого паттерн State и предлагается. Можно попробовать Ваш класс разбить на несколько состояниний таких как: AsyncState, SyncState1, SyncState2, SyncState3. В синхронных состояниях асинхронные запросы отправляются в очередь и никак не обрабатываются. Обрабатываются лишь синхронные запросы, в случае успеха - переход в другое состояние. Как только синхронные состояния выполнились, происходит переход в асинхронное состояние, в котором происходит разгребание накопившейся очереди. |
|||
|
||||
| xbarmaglot |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 149 Регистрация: 28.8.2012 Репутация: нет Всего: нет |
Guinness, то есть автомат ?
Дело в том, что переходы у меня сейчас реализованы по таймауту. То есть если я послал запрс и в течении определенного времени не получил ответа, то бросаю исключение. Автомат должен тогда перейти в конечное состояние. Можно ли сделать переходы, зависимые от времени ? P.S. Да и про сам автомат не совсем понял как реализовать. Тут вроде описано http://doc.crossplatform.ru/qt/4.7.x/statemachine-api.html Но в моем случае есть данные, например, 3 типов. Они могут отправляться и приниматься объектом. При получении данных определенного типа происходит переход в определенное состояние. |
|||
|
||||
| Guinness |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 310 Регистрация: 21.6.2009 Где: Зеленоград Репутация: 2 Всего: 10 |
Да. Просто в паттернах проектирования его называют State. Конечно можно, timerEvent никто не отменял). Просто при переходе в другое состояние запускается таймер, если timerEvent происходит раньше, чем приходят данные, то происходит переход в ошибочное состояние, ну либо куда Вам необходимо.
Почитайте у GoF паттерн State. Вроде понятно описан у них. А ссылочка у меня не открылась. Кстати, на msdn были какие-то статьи по statemachine. Попробуйте сначала нарисовать все состояния как кружочки и объединить их ребрами, написав на них условия перехода. Потом напишите интерфейс общий для всех классов состояний. Дальше уже дело техники. Так просто мне маловато информации, чтобы представлять задачу) |
|||
|
||||
| xbarmaglot |
|
||||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 149 Регистрация: 28.8.2012 Репутация: нет Всего: нет |
Guinness, я так и думал, что малой кровью не обойдется... Будет время обязательно займусь автоматами. Но сейчас нужно, чтоб работало... Вот есть синхронный метод
то есть вызвав данный метод он либо завершится успешно, либо нет. Но если отправка данных и прием в разных методах, то я не совсем понимаю как реализовать то, что я хочу... |
||||||
|
|||||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 24 Всего: 196 |
xbarmaglot, любая программа - это машина состояний. Вот только далеко не всегда их конечное количество. Не обязательно делать явный конечный автомат, можно сделать проще - при отправке запроса сохранять контекст обработки ответа в очереди. Когда приходит ответ, то ты смотришь, подходит ли он к тому контексту, что первый в очереди, если подходит, то передает его контексту. Если нет, то значит это что-то асинхронное.
|
|||
|
||||
![]()
|
| Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets" | |
|
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |