Russian Qt Forum

Qt => Работа с сетью => Тема начата: JamS007 от Январь 03, 2011, 18:36



Название: Класс сетевого сообщения
Отправлено: 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, то - данные потеряны.

Как мне реализовать корректную передачу сообщения? Или может быть будут другие мысли?
В любом случае спасибо.


Название: Re: Класс сетевого сообщения
Отправлено: JamS007 от Январь 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 и предоставит методы для ее обработки.

Объективная критика приветствуется.


Название: Re: Класс сетевого сообщения
Отправлено: vunder от Январь 04, 2011, 19:02
На счет использования метода decode(): не лучше ли использовать Qt RTTI и стандартные методы сохранения Q_OBJECT.


Название: Re: Класс сетевого сообщения
Отправлено: JamS007 от Январь 04, 2011, 19:50
Цитировать
не лучше ли использовать Qt RTTI и стандартные методы сохранения Q_OBJECT

Может быть, но боюсь это будет критично по скорости. Или нет? Напомню, речь идет о сообщениях передаваемых по сети, их количество достаточно велико. Думаю, что интервал "несколько сообщений в секунду" будет привычным делом.


Название: Re: Класс сетевого сообщения
Отправлено: vunder от Январь 06, 2011, 09:40
У меня по такому принципу работает delphi-приложение, и скорости там больше чем несколько штук в секунду. Тем более здесь будет сохранение в поток, а не в файл, что намного быстрее.
Я за RTTI. Это очень упрощает разработку приложения при остутмвие этапа проектирования (по моему опыту это как раз русский вариант). И все что нужно для нового сообщения - отнаследовать новый класс и добавить нужные свойства, т.е. воспользоваться всери прелестями парадигмы ООП


Название: Re: Класс сетевого сообщения
Отправлено: JamS007 от Январь 06, 2011, 21:47
Тогда подскажите, пожалуйста, как можно сохранить наследника QObject в поток? Я с таким не сталкивался и поэтому даже не знаю что искать.