PDA

View Full Version : read data from QtDatastream



Nio74
12th March 2019, 06:21
Good day,

I have a server with the method for read data from database and send a client(If you have suggestion is very accepted)


void ServerThings::readClient()
{
QTcpSocket *clientSocket = static_cast<QTcpSocket*>(sender());
QDataStream in(clientSocket);
//in.setVersion(QDataStream::Qt_5_10);
for (;;)
{
if (!m_nNextBlockSize)
{
if (clientSocket->bytesAvailable() < sizeof(quint16)) { break; }
in >> m_nNextBlockSize;
}

if (clientSocket->bytesAvailable() < m_nNextBlockSize) { break; }
QString str;
in >> str;

emit gotNewMesssage(str);

m_nNextBlockSize = 0;

if (sendToClient(clientSocket, str) == -1)
{
qDebug() << "Some error occured";
}
}
}


qint64 ServerThings::sendToClient(QTcpSocket *socket, const QString &str)
{


QByteArray arrBlock;
Q_ASSERT(socket);
QDataStream out(&arrBlock,QIODevice::WriteOnly);
QSqlQuery query;
query.prepare("SELECT * FROM tabripa where Nbusta =(?)");
query.bindValue(0, str);
query.exec();
while (query.next()) {
const QSqlRecord record = query.record();
for(int i=0; i < record.count(); i++)
out << record.value(i).toString();
}
return socket->write(arrBlock);


}


I now I should receive the data and transform the various records into (string, int, float etc) but I don't know how to do it, can you help me?

anda_skoa
12th March 2019, 08:37
Your readClient() method is not very robust.

If you receive the block size but not enough data to read the block then your method will interpret the next data as the next block size when new data arrives.

You need to remember which state of the reading/decoding process you are in.

As for sendToClient(): why do you write a string and not also use QDataStream?

Cheers,
_

Nio74
12th March 2019, 18:15
As for sendToClient(): why do you write a string and not also use QDataStream?

Cheers,
_

can you explain yourself better? I Send QbyteArray.

anda_skoa
12th March 2019, 23:12
Right, sorry, got confused by the toString() calls.

What you are looking for is to use the actual column data type instead of converting each field to string.
Otherwise you have to parse the strings at the client side.

Cheers,
_

Nio74
13th March 2019, 06:15
yes I would like to do this but how can I send the real data Qdatastream if I am not mistaken it only accepts QbyteArray, could someone give me a small example? Also of only three columns of the database eg (Name "String") and (Nbusta "Int") see attached photo where a line of the ACCESS database is shown
13045

anda_skoa
13th March 2019, 07:17
yes I would like to do this but how can I send the real data Qdatastream if I am not mistaken it only accepts QbyteArray

The "shift" operators (<< and >>) of QDataStream have several overloads.



could someone give me a small example?




QBuffer buffer;

{
buffer.open(QIODevice::WriteOnly);
QDataStream stream(&buffer);

double d = 3.1415;
qint32 i = 42;
QString s = "Hello World";

stream << d << i << s;

buffer.close();
}

{
buffer.open(QIODevice::ReadOnly);
QDataStream stream(&buffer);

double d = 0;
qint32 i = 0;
QString s;

stream >> d >> i >> s;

buffer.close();

qDebug() << "d=" << d << ", i=" << i << ", s=" << s;
}


Cheers,
_

Lesiok
13th March 2019, 07:17
QDataStream have operators << and >> for for all basic data types.

Nio74
13th March 2019, 08:16
Thanks for your patience. Then it would be better if I extract all the server data I insert myself into variables and send them directly to clients without going through QbyteArray? Afterwards in the Client can I receive them separately?

anda_skoa
13th March 2019, 08:58
The important part is to convert the values from the query into the actual data type before writing into the data stream.

You likely also want a "header" like in the other direction, e.g. a number that indicates the size of the message to wait for before decoding.

Cheers,
_

Nio74
13th March 2019, 10:14
You likely also want a "header" like in the other direction, e.g. a number that indicates the size of the message to wait for before decoding.

Cheers,
_

I will try to redo the server, can you give an example of the client method? So I'm sure I'm on the right track,Tank :o

Nio74
13th March 2019, 13:29
{
buffer.open(QIODevice::ReadOnly);
QDataStream stream(&buffer);

double d = 0;
qint32 i = 0;
QString s;

stream >> d >> i >> s;

buffer.close();

qDebug() << "d=" << d << ", i=" << i << ", s=" << s;
}

Sorry I did not see

Added after 16 minutes:

should I always use the QByteArray for send data at client?

13046

Lesiok
13th March 2019, 13:54
First of all don't use construction like this :
query.exec("SELECT * FROM...");
query.record().value(0)...
query.record().value(1)...
...Such SELECT does not guarantee the order of columns. Use
query.exec("SELECT code,pCost,pPublic FROM...");or
query.record().value("cost")...
Second socket is only a pipe. You can not guarantee that one socket.write () operation corresponds to one socket.read () operation. You must provide logic that will pick up the packets of bytes correctly, glue them and interpret them.

Nio74
14th March 2019, 04:56
I did so and It's Work :))))

side Server:


qint64 ServerThings::sendToClient(QTcpSocket *socket, const QString &str)
{


QByteArray byteArray;
// QBuffer buffer(&byteArray);

//buffer.open(QIODevice::WriteOnly);
QDataStream stream(&byteArray,QIODevice::WriteOnly);
QSqlQuery query;
query.prepare("SELECT Nbusta,costo,vendita FROM tabripa where Nbusta =(?)");
query.bindValue(0, str);
query.exec();
while (query.next()){
if(query.isValid()){
code = query.record().value("Nbusta").toInt();
pCost = query.record().value("costo").toDouble();
pPublic = query.record().value("vendita").toDouble();

stream << code <<pCost << pPublic ;

//buffer.close();
}

}

return socket->write(byteArray);


}

side Client:


void ClientServices::readyRead()
{
QDataStream in(tcpSocket);//QtcpSocket

int code = 0;
double pCost = 0;
double pPublic = 0;

in >> code >> pCost >> pPublic;

qDebug() << code << pCost << pPublic;



}
I did not use the Qbuffer because on the client I am not able to integrate it, but if I use it on the server side and on the client no the data is received the same. How does it look? We accept suggestions!