[英]How to send vector with class by QTcpSocket
我試圖從客戶端向服務器發送帶有 class 的向量。 數據在sockets之間發送,但是當我想將它們寫入控制台時,服務器崩潰了
#include <QCoreApplication>
#include <QTcpSocket>
#include <QDataStream>
#include "data.h"
//client
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
std::vector< data > wektor;
data asd;
asd.setName("asd");
wektor.push_back(asd);
wektor.push_back(asd);
for (data w : wektor){
qDebug()<<w.getName();
}
quint16 rozmiarSampla = sizeof( wektor[0] );
quint16 ileSampli = wektor.size();
QTcpSocket socket;
socket.connectToHost("127.0.0.1",9999);
if( !socket.waitForConnected() )
return 1;
QDataStream stream(&socket);
QString typ("Paczka z buforem");
stream << typ << rozmiarSampla << ileSampli;
stream.writeRawData( reinterpret_cast<const char*>( wektor.data() ) , rozmiarSampla * ileSampli );
socket.flush();
socket.waitForBytesWritten();
return 0;
}
服務器
#include <QCoreApplication>
#include <QTcpServer>
#include <QTcpSocket>
#include <QDataStream>
#include <QScopedPointer>
#include "data.h"
#include <iostream>
#include <string.h>
//serwer
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
std::vector< data > wektor;
QString typ;
quint16 rozmiarSampla;
quint16 ileSampli;
QTcpServer serwer;
serwer.listen(QHostAddress::AnyIPv4,9999);
if( !serwer.waitForNewConnection(30000) )
return 1;
QScopedPointer<QTcpSocket> socket{ serwer.nextPendingConnection() };
if(! socket->waitForReadyRead() )
return 1;
QDataStream stream(socket.data());
stream >> typ >> rozmiarSampla >> ileSampli;
if( rozmiarSampla == sizeof( wektor[0] ) ) {
wektor.resize(ileSampli);
stream.readRawData( reinterpret_cast<char*>( wektor.data() ) , rozmiarSampla * ileSampli );
} else {
stream.skipRawData(rozmiarSampla * ileSampli);
}
qDebug() << "Typ: " << typ;
qDebug() << "RozmiarSampla: " << rozmiarSampla;
qDebug() << "IleSampli: " << ileSampli;
qDebug()<<wektor.size();
qDebug()<< wektor[0].getName();
return a.exec();
}
數據.H
#ifndef DATA_H
#define DATA_H
#include <QtCore>
class data
{
public:
data();
void setName(QString name);
QString getName();
private:
QString Name;
};
#endif // DATA_H
數據文件
#include "data.h"
#include <QtCore>
data::data()
{
this->Name = "null";
}
void data::setName(QString name)
{
this->Name = name;
}
QString data::getName()
{
return this->Name;
}
嘗試從數據 class 打印名稱時服務器崩潰。我不明白為什么會這樣,有人可以向我解釋錯誤是什么嗎? 當我試圖發送一個由數據組成的向量時,例如 int,一切正常。
正如評論所建議的那樣,這里的問題是 QString 不是一個簡單的可復制類型。
那是什么意思? 好吧,這是一個簡單的 model QString 的樣子:
class QString {
public:
// all of the methods
private:
// QString doesn't store the data directly, it stores a pointer to the string data
Data* data;
};
參考: https://codebrowser.dev/qt5/qtbase/src/corelib/text/qstring.h.html#979
因此,當您執行stream.writeRawData( reinterpret_cast<const char*>( wektor.data() ), rozmiarSampla * ileSampli )
時,您正在復制 QString 中包含的數據......但它包含的只是一個指針,你是不復制字符串數據本身。 當然,只是指向數據的指針。 該指針在套接字的另一側是無意義的。
那么如何解決這個問題呢? 有很多方法,但我建議專門針對您的類型使用QDataStream
stream 運算符:
// In your data class header file
QDataStream& operator<<(QDataStream& stream, const data& d);
QDataStream& operator>>(QDataStream& stream, data& d);
// and in the cpp file
QDataStream& operator<<(QDataStream& stream, const data& d) {
stream << d.getName();
return stream;
}
QDataStream& operator>>(QDataStream& stream, data& d) {
QString name;
stream >> name;
d.setName(name);
return stream;
}
當給定一個像這樣的QString
時, QDataStream
知道如何序列化QString
。 這些專門化的作用是向QDataStream
展示如何序列化data
。 現在有了這個,您可以將您的std::vector<data>
序列化為數據 stream,例如:
stream << wektor.size(); // serialize the number of instances
for (const auto& d : wektor)
stream << d; // serialize each data instance
你可以用類似的東西反序列化它們:
size_t wektorSize;
stream >> wektorSize;
std::vector<data> wektor{wektorSize};
for (auto& d : wektor)
stream >> d;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.