PDA

View Full Version : QSslSocket to much data?



Qiieha
27th January 2012, 15:32
Hi
I developed a Client Server Application with QSslSocket. It works very fine, but if I transfer a big amount of QDataStream
the client receives nothing. The readyReadSlot of the Client gets executed about 23 times, but in the end there is no data.

Does somebody know, what's wrong??

thank u

wysota
27th January 2012, 17:53
You are probably using QDataStream incorrectly.

Qiieha
27th January 2012, 22:25
Thank u...
No i use it correctly...like fortune example....

wysota
27th January 2012, 22:40
You mean the broken fortune example that doesn't expect to receive much data?

Ok then, I'll be here in case you eliminate all other possibilities and come to a conclusion you are not using QDataStream correctly.

Qiieha
29th January 2012, 19:07
ok, i use it this way:

server send-method


void Server::send_xml_data(QString message) {
blockSize = 0;
QString out_string = message;
QByteArray block;
QDataStream out_stream(&block, QIODevice::WriteOnly);
out_stream.setVersion(QDataStream::Qt_4_7);
out_stream << (qint16)0;
out_stream << out_string;
out_stream.device()->seek(0);
out_stream << quint16(block.size() - sizeof(quint16));
socket->write(block);
}

client-readyReadSlot-method:


void Client::readyReadSlot()
{
qDebug() << "readyReadSlot()";
QDataStream in(socket);
in.setVersion(QDataStream::Qt_4_7);
if (blockSize == 0) {
if (socket->bytesAvailable() < (int)sizeof(quint16))
return;
in >> blockSize;
}
if (socket->bytesAvailable() < blockSize)
return;

QString result;
in >> result;
receive(result); //process my data
}

wysota
29th January 2012, 21:03
What if blockSize > size of the socket's read buffer?

ChrisW67
30th January 2012, 01:16
... or the serialised form of the string is longer than 65536 bytes at the sending end?

Qiieha
30th January 2012, 08:00
Ok :), you persuaded me...but how can I work around?

How can I enlarge the socket's read buffer?

ChrisW67
30th January 2012, 08:11
How many bytes is a "big amount of QDataStream"?

Qiieha
30th January 2012, 08:22
For example 133612 bytes...

ChrisW67
30th January 2012, 08:36
Firstly, your 16-bit byte count for the transmitted packet is inadequate.

In short, don't rely on the operating system or Qt to buffer data for you, and don't assume it will turn up all at once. Since the data packet can easily fit into memory this is the usual flow of things:

You have a QByteArray buffer to hold unprocessed received data (as a member of the Client class)
In response to readyRead():
Add all available bytes to that buffer.
While the buffer contains a complete packet, process that packet and remove it from the front of the buffer.
Leave any unprocessed part-packet in the buffer and leave the readyRead() handler.

Qiieha
30th January 2012, 09:17
Thank you...
Ok, I'll try it. And how do I check whether the packet is complete? Should I ask, if there is a </xml-response>-tag in the datastream everytime?

Added after 32 minutes:

Now I use that way:

server send-method:


void Server::sendXML(QString message)
{
QByteArray block;
block.append(message);
socket->write(block);
}


client


void Client::readyReadSlot()
{
qDebug() << "readyReadSlot()";
buffer.append(socket->readAll());
QString result(buffer);
if(!result.contains("</xml-response>"))
return;
receive(result);
}


Is this OK?

wysota
30th January 2012, 09:49
No, it's not ok. It will fail with this xml:
<xml-response/>
or this one:
<xml-response>
<a>
<b/>
<xml-response>
</xml-response>


or this one:
<xml-response>
<a/>
</xml-response>
<xml-response>
<a/>
</xml-response>

If you have xml data it is best to use a solution such as QXmlStreamReader that can resume the process of parsing when more data is available.

Qiieha
30th January 2012, 12:44
So my Buffer is instead of a QByteArray a QXmlStreamReader.
In readyReadSlot I add the the incoming package to my reader (addData()) and
call xml_reader.atEnd() and process the data or wait for next packet.

wysota
30th January 2012, 15:10
Is there a question here somewhere or is your problem solved?

Qiieha
31st January 2012, 08:27
The atEnd() returns false everytime, but I will find the bug....If I solve the problem, I mark the thread as Solved....

wysota
31st January 2012, 10:26
How are you using the parser?

Qiieha
31st January 2012, 20:04
while(!buffer.atEnd() && !buffer.hasError()) {

QXmlStreamReader::TokenType token = buffer.readNext();

if(token == QXmlStreamReader::EndElement && buffer.name() == "xml-response") {
processData(result);
//stop method
}

}

Does this solution have a good performance. And I have to save the data additional in a QByteArray, because I neet the result as a QString.

wysota
31st January 2012, 20:52
Your code doesn't make sense. Please read how to use QXmlStreamReader instead of blindly writing code.

ChrisW67
31st January 2012, 22:56
...because I neet the result as a QString.

Exactly what is the "result" you are trying to achieve? A string representing the entire XML document, a string extracted from part of the document, a string derived from the document by some algorithm...? Ask yourself if sending an XML document is the correct approach in the first place.

Qiieha
1st February 2012, 21:56
A QString, which represents an entire xml doc


<xml-response>
<person>
<name>charlie</name>
<family-name>harper</family-name>
</person>
<xml-respone>

for example....I serialize it later with qdom....don't want to do it in readyread-slot....
I just want to ensure that the full string is transfered....

wysota
1st February 2012, 22:56
If you want to be sure then you need to parse this string while reading it. If you later want to reparse it again using QDomDocument, that's your problem. Using QDataStrem doesn't make sense here and QXmlStreamReader seems perfect for the task of processing the document.