Название: Десериализация данных в TCP Отправлено: darkfog от Июнь 07, 2018, 14:07 Создал простые клиент сервер. И вот вопрос при сериализации и отправке нескольких классов(или в простом случае несколько переменных разных типов), как определить на стороне клиента какой класс пришел для правильной десериализации? Можно при отправке в потоке QDataStream после начальных значений размера пакета добавить числовой идентификатор типа(класса). И на стороне сервера делать проверку if чтобы использовать нужную десериализацию. Но если классов для передачи бедет например 100 это не выглядит хорошо. Есть ли красивый способ решить эту задачу?
Название: Re: Десериализация данных в TCP Отправлено: deMax от Июнь 07, 2018, 15:06 Передавайте строку с именем класса.
Название: Re: Десериализация данных в TCP Отправлено: darkfog от Июнь 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 он побыстрее но я хочу узнать есть ли другой способ узнать какой тип(класс) пришел от клиента. Проблема не в десериализации, а в определении пришедшего типа(повышение быстродействия). Может есть хороший метод для этого. Подобное должно использоваться в многопользовательских играх по идее. Название: Re: Десериализация данных в TCP Отправлено: sergek от Июнь 07, 2018, 16:37 Без реализации какого-то протокола вам не обойтись. Передаваемые данные в любом случае должны предваряться заголовком фиксированной длины, где, как минимум, должна содержаться информация о размере передаваемых данных и о типе.
Название: Re: Десериализация данных в TCP Отправлено: deMax от Июнь 07, 2018, 17:08 Ну пришли к вам данные, дальше что хотите? вызвать одну из 100 функций передав ей обьект? тогда - QMap<QString, std::function> callBackMap
Можно с библиотеками заморочиться вызывая функции по имени. Или готовые протоколы заюзать: json, protobuf... выбор за Вами... Название: Re: Десериализация данных в TCP Отправлено: darkfog от Июнь 19, 2018, 15:29 Короче решил делать через switch с передачей идентификатора класса и не парится пока.
|