LINUX.ORG.RU

Клиент-серверное взаимодействие. Объясните. (Qt)

 ,


0

3

Объясните, пожалуйста, как правильно реализовывать протокол общения. Т.е. как отсылать команды, принимать ответы - понятно. А вот как правильно (быстро, минимально) написать, что после комманды Hello должен быть ответ Hi, а после команды Auth должен быть ответ Ok, а на клиенте при ответе Ok на команду Auth нужно не валиться с ошибкой, а слать логин-пароль? Не совсем понимаю, как правильно задавать правильную последовательность пар команда-ответ.

ЗЫ. Особенно, в следствие того, что прием ответа клиентом осуществляется не сразу, а по сигналу readyRead :)

ЗЗЫ. Есть предположение, что нужно в классе сохранять эту последовательность команда-ответ. Может быть, так и сделать, хранить массив структур-соответствий, а при анализе полученного ответа пробегать по этому массиву и анализировать, на каком этапе общения мы сейчас находимся?

★★★★★

А вот как правильно (быстро, минимально) написать, что после комманды Hello должен быть ответ Hi, а после команды Auth должен быть ответ Ok, а на клиенте при ответе Ok на команду Auth нужно не валиться с ошибкой, а слать логин-пароль?

Хранить в контроллёре состояние, хотя бы в виде

enum State {
  State_SentAuthRequest,
  State_SentLoginPassw,
  State_Finished
};
В общем, класс, который управляет этой частью клиент-серверного общения, должен действовать как конечный автомат.

ЗЫ. Особенно, в следствие того, что прием ответа клиентом осуществляется не сразу, а по сигналу readyRead :)

Запрошенный QUrl обычно годится как уникальный идентификатор запроса, так что подвешенный на соответствующий сигнал класс может просто сверять url от QNetworkReply с изначально запрошенным урлом и при совпадении принимать как ответ.

quiet_readonly ★★★★
()
Ответ на: комментарий от bvn13

В статье «автоматное программирование» пролистайте сразу к примерам кода.

Про автоматы есть две категории статей: статьи о DFA и формальных грамматиках (не ваш случай) и автоматное программирование. Вот второе можно погуглить, при желании.

quiet_readonly ★★★★
()
Ответ на: комментарий от trex6

В QML есть встроенные состояния (да, я Капитан), а вот про Qt-шные впервые слышу, тем более что в большинстве случаев хватает обычного enumeration.

ТСу: в более сложных случаях есть паттерн «Состояние», можете запомнить на всякий пожарный.

quiet_readonly ★★★★
()
Последнее исправление: quiet_readonly (всего исправлений: 1)
Ответ на: комментарий от trex6

QStateMachine хорош, но QAbstractState это QObject со всеми вытекающими последствиями, если есть куча элементов с состояниями то оверхед может быть значителен. Для простых случаев часто хватает enum'а с состоянием и ручной обработки переходов. Есть еще варианты с Boost State Chart и Boost MSM.

bjorn
()
Ответ на: комментарий от bjorn

это QObject со всеми вытекающими последствиями, <...> оверхед может быть значителен

А где-нибудь есть достойные внимание статьи на эту тему? Насколько много оверхеда приносит дополнительное наследование класса от QObject ради одного-двих слотов/сигналов?

trex6 ★★★★★
()

Если возможно делай stateless протокол. Так надёжнее будет. Кури nfs или http v1.1.

Кстати readyRead не всегда будет соответсвовать запросу. Если ты не кодируешь команду и ответ одним байтом, то тебе может прийти полкоманды например.

nanoolinux ★★★★
()
Ответ на: комментарий от trex6

Констуктор и деструткор будут делать дополнительно всякой фигни чуток. Да и сам механизм сигналов слотов тоже имеет оверхед. К сожалению ссылок на исследования и измерения не имею.

nanoolinux ★★★★
()
Ответ на: комментарий от quiet_readonly

Покамест сделал на нумераторах. Вполне читаемо, понятно и быстро.

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от nanoolinux

Думаю, что это слишком на данный момент.

про частичность данных в readyRead знаю, спасибо. :) читаю до полного «прихода» данных.

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от trex6

Интересно, надо будет изучить, спасибо.

bvn13 ★★★★★
() автор топика

К каждому подключившемуся клиенту привязываешь некий класс (как минимум QTcpSocket* у тебя в нем будет, если твой протокол поверх TCP). Еще в этом классе хранишь переменную-состояние и переключаешь ее в зависимости от происходящих событий. В общем как написали выше - обычный конечный автомат.

m0rph ★★★★★
()

В protobuf есть services с кодогенерацией и гейшами.

dmfd
()
Ответ на: комментарий от nanoolinux

механизм сигналов слотов тоже имеет оверхед

Там все в целом понятно. Работает через map<string, method> если в 2х словах. Конструкторы покурю еще, но надеялся на уже проведенное комплексное исследование.

trex6 ★★★★★
()

Прозвучит наверное глупо, но почему бы не использовать синхронное запись/чтение сети? Т.е. пока ответ приходит не «Hi» шлем «Hello», потом пока не прийдет ответ «Ok» - шлем «Auth».

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.