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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Десериализация данных в TCP  (Прочитано 4472 раз)
darkfog
Гость
« : Июнь 07, 2018, 14:07 »

Создал простые клиент сервер. И вот вопрос при сериализации и отправке нескольких классов(или в простом случае несколько переменных разных типов), как определить на стороне клиента какой класс пришел для правильной десериализации? Можно при отправке в потоке QDataStream после начальных значений размера пакета добавить числовой идентификатор типа(класса). И на стороне сервера делать проверку if чтобы использовать нужную десериализацию. Но если классов для передачи бедет например 100 это не выглядит хорошо. Есть ли красивый способ решить эту задачу?
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #1 : Июнь 07, 2018, 15:06 »

Передавайте строку с именем класса.
Записан
darkfog
Гость
« Ответ #2 : Июнь 07, 2018, 15:29 »

Передавайте строку с именем класса.

Класса как такового сейчас нет(не знаю какой будет). Представь что первый раз передается строка QString, а второй картинка QImage. QDataStream может их сам сериализовать, но вот определить что пришла именно картинка не может. Нужно самому создать переменную  QImage im и в нее поместить значение из потока.    

QTcpSocket* pClientSocket = (QTcpSocket*)sender();
QDataStream in(pClientSocket);
QImage im;
in >> im;

Что бы понять что пришло изображение я на второе место после размера отправленного пакета помещаю идентификатор типа(например 1)

QTcpSocket* m_pTcpSocket;//объявлен в .h

QByteArray  arrBlock;
QDataStream out(&arrBlock, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_3);
QByteArray pic;
int type;
QFile file("D:/image");
file.open(QIODevice::ReadOnly);
pic = file.readAll(); //bit-picture
type = 1;
out << quint16(0) << type << pic;
m_pTcpSocket->write(arrBlock);

И на стороне сервера при получении делаю проверку полученного идентификатора типа.

QTcpSocket* pClientSocket = (QTcpSocket*)sender();
    QDataStream in(pClientSocket);
    in.setVersion(QDataStream::Qt_5_3);
    for (;Подмигивающий
    {
        if (!m_nNextBlockSize)
        {
            if (pClientSocket->bytesAvailable() < (int)sizeof(quint16))//проверяем размер
            {
                break;
            }
            in >> m_nNextBlockSize;
        }

        if (pClientSocket->bytesAvailable() < m_nNextBlockSize)
        {
            break;
        }
        QByteArray image;
        QImage im;
        int type;
        in >> type;
        if(type == 1)//проверяем тип
        {
            in >> image;
            im = QImage::fromData(image, "TGA");
            m_ptxt->setPixmap(QPixmap::fromImage(im));
            m_ptxt->show();
            m_nNextBlockSize = 0;
        }

И вот представте что передано дофига разных типов переменных, и каждый раз проверка на if не выглядит хорошим решением. Можно использовать switch он побыстрее но я хочу узнать есть ли другой способ узнать какой тип(класс) пришел от клиента.
Проблема не в десериализации, а в определении пришедшего типа(повышение быстродействия). Может есть хороший метод для этого. Подобное должно использоваться в многопользовательских играх по идее.
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 861


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #3 : Июнь 07, 2018, 16:37 »

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

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #4 : Июнь 07, 2018, 17:08 »

Ну пришли к вам данные, дальше что хотите? вызвать одну из 100 функций передав ей обьект? тогда - QMap<QString, std::function> callBackMap
Можно с библиотеками заморочиться вызывая функции по имени.
Или готовые протоколы заюзать: json, protobuf...

выбор за Вами...
Записан
darkfog
Гость
« Ответ #5 : Июнь 19, 2018, 15:29 »

Короче решил делать через switch с передачей идентификатора класса и не парится пока.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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