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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Класс сетевого сообщения  (Прочитано 3182 раз)
JamS007
Гость
« : Январь 03, 2011, 18:36 »

Доброго времени суток.

Постараюсь максимально подробно описать ситуацию. Есть клиент-серверное приложение. Общение между клиентом и сервером происходит посредством сообщений, но количество их разновидностей очень велико. Дело в том, что сервер должен обрабатывать множество разных запросов от клиента, которые различаются как количеством аргументов, так и их типами.

Я пробовал писать в стиле С. То есть написать несколько enum-ов и проверять с их помощью всевозможные вариации сообщения. Но это оказалось очень неудобно. Немного поразмыслив решил что этот способ мне не подходит, наверняка есть что-то более удобное и практичное.

Потом мне в голову пришла мысль написать базовый класс сообщения, от которого наследовать все другие сообщения разных типов. Что то типа
QNetMessage -> {QFirstTypeMessage, QSecondTypeMessage ...}

Такой подход мне нравиться куда больше. Но проблема вот в чем: как мне на другом конце определить тип сообщения? Хочется что-то типа полиморфизма. Ну к примеру:
 
Код
C++ (Qt)
if (message && message->type() == QNetMessage::MT_FirstTypeMessage){
       QFirstTypeMessage *message = static_cast<QFirstTypeMessage *>(message);
 
       // parsing
       // ...
   }

Данные приходят в бинарном виде, а это значит, что если клиентом было передано QFirstTypeMessage, а на сервере прочитано QNetMessage, то - данные потеряны.

Как мне реализовать корректную передачу сообщения? Или может быть будут другие мысли?
В любом случае спасибо.
Записан
JamS007
Гость
« Ответ #1 : Январь 03, 2011, 23:13 »

Пока придумал только такое решение:

Код
C++ (Qt)
class PNetMessage
{
public:
   enum Type { None = 0, NetMessage = 1 };
 
   PNetMessage(Type type = NetMessage);
 
   virtual void decode();
   void setType(Type type);
   void setData(const QByteArray &data);
 
   quint16 type();
 
   friend QDataStream &operator<<(QDataStream &, const PNetMessage &);
   friend QDataStream &operator>>(QDataStream &, PNetMessage &);
 
private:
   QByteArray messageData;
   quint16    messageType;
};
 

Объект класса будет создаваться каждый раз, когда будут приходить данные. Потом в этот объект с помощью QDataStream будут заноситься данные с сокета. Далее, в зависимости от типа сообщения (messageType) данный объект будет преобразован к классу-наследнику, который с помощью метода decode() декодирует полученную информацию из messageData и предоставит методы для ее обработки.

Объективная критика приветствуется.
Записан
vunder
Гость
« Ответ #2 : Январь 04, 2011, 19:02 »

На счет использования метода decode(): не лучше ли использовать Qt RTTI и стандартные методы сохранения Q_OBJECT.
Записан
JamS007
Гость
« Ответ #3 : Январь 04, 2011, 19:50 »

Цитировать
не лучше ли использовать Qt RTTI и стандартные методы сохранения Q_OBJECT

Может быть, но боюсь это будет критично по скорости. Или нет? Напомню, речь идет о сообщениях передаваемых по сети, их количество достаточно велико. Думаю, что интервал "несколько сообщений в секунду" будет привычным делом.
Записан
vunder
Гость
« Ответ #4 : Январь 06, 2011, 09:40 »

У меня по такому принципу работает delphi-приложение, и скорости там больше чем несколько штук в секунду. Тем более здесь будет сохранение в поток, а не в файл, что намного быстрее.
Я за RTTI. Это очень упрощает разработку приложения при остутмвие этапа проектирования (по моему опыту это как раз русский вариант). И все что нужно для нового сообщения - отнаследовать новый класс и добавить нужные свойства, т.е. воспользоваться всери прелестями парадигмы ООП
Записан
JamS007
Гость
« Ответ #5 : Январь 06, 2011, 21:47 »

Тогда подскажите, пожалуйста, как можно сохранить наследника QObject в поток? Я с таким не сталкивался и поэтому даже не знаю что искать.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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