![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() ![]() |
![]() |
leonneon_89 |
![]()
Сообщение
#1
|
Студент ![]() Группа: Участник Сообщений: 20 Регистрация: 5.4.2013 Пользователь №: 3779 Спасибо сказали: 0 раз(а) Репутация: ![]() ![]() ![]() |
В общем немного о программе.
Есть клиент, который выполняет функции: 1. Отправлять запрос серверу. 2. Отправлять сообщения серверу. 3. Получать сообщения от сервера. Есть сервер, выполняющий функции: 1. Он получает сообщения от клиента производит действия на сервере, отсылает ответ. 2. Сам посылает сообщения клиенту. Программа работает в таком режиме. Устанавливаем соединение, а дальше посылаем и принимает сообщения от сервера, после выхода из программы закрываем соединение. Вся передача сообщений происходит в одном сокете. Сервер состоит из clientsocket.h - наследуется от QTcpSocket в котором производятся вычисления, server.h - наследуется от QTcpServer переопределяет incomingConnection и главной функции. На сервере clientsocket.cpp используем QTimer для посылки самостоятельных сообщений клиенту. slot для отправки сообщений.
Так же, там есть функция отправки ответа на сообщения клиента.
Вообщем у меня возник вопрос. Когда клиент посылает много сообщений серверу. Мне кажется сервер иногда не успевает обрабатывать, все полученные сообщения от клиента и отсылает только некоторые из них, из за этого клиент работает не корректно. Есть предположение что сервер не успевает записывать данные в сокет, так как он в то же время посылает уровень сигнала клиенту. Я на сервере используются две функции write(). Как мне избавится от такой проблемы, чтобы сервер принимал все сообщения от клиента и записывал все ответы, и в то же время посылал уровень сигнала в виде сообщения? |
|
|
lanz |
![]()
Сообщение
#2
|
![]() Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
Цитата Мне кажется сервер иногда не успевает обрабатывать, все полученные сообщения от клиента и отсылает только некоторые из них, из за этого клиент работает не корректно. А что qDebug, подтверждает факт потери сообщений? Цитата Есть предположение что сервер не успевает записывать данные в сокет, так как он в то же время посылает уровень сигнала клиенту. В то же время он не может ничего делать, если у него не несколько тредов/процессов. Сигналы/слоты НЕ обрабатываются, пока управление не вернется к event loop. |
|
|
leonneon_89 |
![]()
Сообщение
#3
|
Студент ![]() Группа: Участник Сообщений: 20 Регистрация: 5.4.2013 Пользователь №: 3779 Спасибо сказали: 0 раз(а) Репутация: ![]() ![]() ![]() |
Цитата А что qDebug, подтверждает факт потери сообщений? Да, qDebug подтверждает факт потери сообщения. На стороне клиента я вывожу команду, которая отправляется серверу и полученный ответ. Цитата В то же время он не может ничего делать, если у него не несколько тредов/процессов. Сигналы/слоты НЕ обрабатываются, пока управление не вернется к event loop. Получается QTimer блокирует вызов Сигналов/слотов? И мне надо использовать треды для решения этой проблемы? |
|
|
lanz |
![]()
Сообщение
#4
|
![]() Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
Цитата Получается QTimer блокирует вызов Сигналов/слотов? И мне надо использовать треды для решения этой проблемы? Ни в коем случае не надо использовать треды для решения проблемы! Это только добавит проблем. write не блокирующая функция. Приложите мимнимальный проект, который иллюстрирует проблему. |
|
|
leonneon_89 |
![]()
Сообщение
#5
|
Студент ![]() Группа: Участник Сообщений: 20 Регистрация: 5.4.2013 Пользователь №: 3779 Спасибо сказали: 0 раз(а) Репутация: ![]() ![]() ![]() |
В общем, вот проект. SupplyUnitMMA - клиент, tripserver - сервер.
сначала запускаем сервер, а потом клиент. Ошибка появляется, когда мы включаем клиент, запускаем автоматический режим, потом переходим в ручной и начинаем быстро изменять положение аттенюатора блока управления, после этого аттенюатор начинает работать не корректно. Будут вопросы по проекту пишите, постараюсь пояснить детали.
Прикрепленные файлы
|
|
|
lanz |
![]()
Сообщение
#6
|
![]() Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
Необязательно нажимать на авто, клиент и сервер попадают в бесконечный цикл.
Итак после поворота ручки клиент посылает серверу сообщение об изменении, в ответ тот посылает одобрение:
Клиент, будучи доволен одобрением выставляет ручку аттеньюатора в одобренное значение: ![]()
Однако коварный Qt подготовил ловушку в виде отслеживания изменения ручки! ![]()
Не успело новое значение примениться, как слот спешит доложить новое значение серверу: ![]()
Который успешно его получает: ![]()
и отправляет свое одобрение: ![]()
Что возвращает нас к началу нашей истории ![]() |
|
|
leonneon_89 |
![]()
Сообщение
#7
|
Студент ![]() Группа: Участник Сообщений: 20 Регистрация: 5.4.2013 Пользователь №: 3779 Спасибо сказали: 0 раз(а) Репутация: ![]() ![]() ![]() |
Спасибо за подробный ответ, у меня возник еще небольшой вопрос, если мы посылаем серверу первоначальный запрос всех состояний, и он нам возвращает сообщение в котором находятся состояния всех аттенюаторов, аттенюаторов у нас несколько штук, мы сохраняем их состояния, в это время все они испускают сигнал об изменении, которые в свою очередь соединяются со своими сигналами и посылают одновременно сообщения серверу о своих изменившихся состояниях. Как это можно избежать? Или можно поставить connection в очередь, чтобы они посылались поочередно? Если у нас два соединения, то можно у одного поставить атрибут Qt::QueuedConnection, который встанет в очередь после connection без атрибута, а если у нас три или более connection, то как тогда быть?
|
|
|
lanz |
![]()
Сообщение
#8
|
![]() Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 690 Регистрация: 28.12.2012 Пользователь №: 3660 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
Я заводил флаг.
Когда сервер присылает команду на изменение - выставляем флаг, после применения всех изменений - сбрасываем. В обработчике события изменения значения оповещаем сервер только если флаг не установлен (изменение происходит от пользователя). Единственная тонкость - нельзя использовать QueuedConnection, поскольку оно вызовется уже после сброса флага. |
|
|
leonneon_89 |
![]()
Сообщение
#9
|
Студент ![]() Группа: Участник Сообщений: 20 Регистрация: 5.4.2013 Пользователь №: 3779 Спасибо сказали: 0 раз(а) Репутация: ![]() ![]() ![]() |
Спасибо, теперь стало более понятней.
![]() |
|
|
![]() ![]() ![]() |
![]() |
Текстовая версия | Сейчас: 17.2.2025, 11:12 |