PDA

View Full Version : QTcpSocket and data size - how do I know the size?



themolecule
27th August 2007, 00:04
I have a client/server application and I am confused about how the receiving side knows when enough data is available.

The sender (which may be client or server) will send a single char to indicate mode, then a list of elements being requested or returned.

for instance, if the client wants to request some variables from the server, it does something like:



void class::sendData()
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);

QChar c('v'); //indicate this is a variable request with 'v' char.
QStringList varlist("var1") << "var2"; //indicate the list of vars being requested.

out << c;
//out << dataSize //how do I calculate this value?
out << varlist;

socket->write(block);
}


how does the receiving side know when enough data is available? In the fortune examples, it writes the size of the string in the first bytes, which is fine for a single string.

But how do I know the size of a QStringList? is it just the sum of the lengths of the strings, or is there a sizeof command which calculates it?

After the request has been made, the recipient would respond with something like:



void class::sendData()
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);

QChar c('V'); //indicate this is a variable response with 'V' char.
QHash<QString, QVariant> vars;
vars["var1"] = QVariant(100);
vars["var2"] = QVariant("some data here");

out << c;
//out << dataSize //how do I calculate this value?
out << vars;

socket->write(block);
}


of course, the real implementation would fetch the values for the QHash from some other place based on the list previously received, and socket is a class member created from the connection.

The documentation says that QHash is serializable, as well as QVariant, so it tells me that the << operator will do its job, but on the receiving side, how do I know how big the data is?

Do I have to write it to a QByteArray, then measure the size of the bytearray, then write the size of the bytearray, then write the bytearray itself? This seems like an awful lot of copying and buffering that could be avoided if I knew the size (which will always be different) ahead of time. If I am sending a long list of variables, this could be expensive!

I was considering creating a blocking TCP thread instead of returning when not enough bytes have arrived, but this has the same problem, because >> does not seem to block. Is there a way to make >> block, or a way to pre-calculate the size instead of putting it in a bytearray?

thanks!

jacek
27th August 2007, 01:49
how does the receiving side know when enough data is available? In the fortune examples, it writes the size of the string in the first bytes, which is fine for a single string.
Yes, but it does it in a generic way:
out << (quint16)0;
...
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));
As you can see the value written at the beginning of the block is calculated from the block size, so it doesn't matter what you write to the data stream in line 2.


But how do I know the size of a QStringList? is it just the sum of the lengths of the strings, or is there a sizeof command which calculates it?
It depends on the encoding scheme you use. QDataStream will use this one (http://doc.trolltech.com/4.3/datastreamformat.html).


Is there a way to make >> block
No, there isn't.

themolecule
27th August 2007, 02:18
ok... well, would it work to do something like



void class::sendData()
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);

QChar c('v'); //indicate this is a variable request with 'v' char.
QStringList varlist("var1") << "var2"; //indicate the list of vars being requested.
QStringList varlist2("var1") << "var2"; //indicate another list of vars.

out << varlist;
out << varlist2;

socket << c << (quint16) out.size() << out;
}


or does abstractSocketItem not use the << syntax? Is this better, or just equivalent? Is it slow to rewind the pointer in a bytearray?

jacek
28th August 2007, 02:19
or does abstractSocketItem not use the << syntax? Is this better, or just equivalent?
No, it doesn't have operator<<. You have to use QIODevice::write().


Is it slow to rewind the pointer in a bytearray?
It shouldn't be. It's probably just a single assignment.