PDA

View Full Version : Continously receive from server using waitforReadyread()



rinku
18th August 2012, 14:12
I am new in QT i have written one server client application in where my server will continuously send some file names to client and client should receive them correspondly one by one.In client side to receive the file names i am using "waitforReadyread()" in a while loop like,

while(sock->waitforreadyReady(300))

{

sock->read(f_name,sock->bytesavailable());

-----

}

So i am recevieng the filenames till that timeout but server send all the file names. i want to receive all the file names from server untill server send some finsh string to client. so please help.

ChrisW67
19th August 2012, 05:02
For a start, don't use the synchronous functions, use the readyRead() signal to fire a slot. When you receive the signal take all the available data and append it to a QByteArray (that's declared as a member variable of the class not a local). If the QByteArray contains the end-of-list marker then process the data from the start of the array to the marker, remove that data from the array, and return from the slot with any remaining data still in the array.

rinku
20th August 2012, 05:57
thnks for your reply m using readyread signal to fire my receiving slot.. so you mean to say i should use QByteArray to receive all the filenames..and what about loop then?can you plz explain me more?

ChrisW67
20th August 2012, 08:30
Your loop is using the blocking waitForReadyRead() function, so it is incompatible with the typical asynchronous non-blocking process.

The general idea (no error checking etc.) is in this code snippet:


class Fetcher: public QObject
{
Q_OBJECT
public:
Fetcher(QObject *p = 0): QObject(p), reply(0) {}

void fetch(const QUrl &url) {
buffer.clear();
reply = nam.get(QNetworkRequest(url));
connect(reply, SIGNAL(finished()), SLOT(slotFinished()));
connect(reply, SIGNAL(readyRead()), SLOT(slotReadyRead()));
}

public slots:
void slotReadyRead() {
buffer.append(reply.readAll());

int index = buffer.indexOf("\n\n"); // a blank line indicates the end
if (index > 0) {
// call something to process buffer.left(index)

// remove the processed data and the blank line
buffer = buffer.mid(index+2);
}
}

void slotFinished() {
reply->deleteLater();
reply = 0;
}

private:
QNetworkAccessManager nam;
QNetworkReply *reply;
QByteArray buffer;
};

rinku
20th August 2012, 10:47
so far whatever i understood is buffer will receive all the filenames as a whole like,
buffer[0]="filename1"
buffer[1]="filename2"
buffer[2]="filename3" etc..then it will check the index number of the last string so i no need send any finishing string.

buffer.left[index] will give me the filename one by one. so can i copy this buffer.left[index] to any char buffer like strcpy(buffer1,buffer.left[index])?
but i m not understanding what buffer = buffer.mid(index+2) is doing.

yeye_olive
20th August 2012, 15:21
so far whatever i understood is buffer will receive all the filenames as a whole like,
buffer[0]="filename1"
buffer[1]="filename2"
buffer[2]="filename3" etc..then it will check the index number of the last string so i no need send any finishing string.

buffer.left[index] will give me the filename one by one. so can i copy this buffer.left[index] to any char buffer like strcpy(buffer1,buffer.left[index])?
but i m not understanding what buffer = buffer.mid(index+2) is doing.
I am afraid this is completely wrong. "buffer" is a QByteArray, which is a simple container representing -- obviously -- an array of bytes. Its elements are bytes, not (pointers to) strings of characters.

Are your server and client using raw TCP sockets to communicate? You seem to be assuming that each "sock->read()" operation will read exactly one file name, but this is not how TCP works. Structured data needs to be serialized and deserialized. I suggest you read this FAQ (http://nitoprograms.blogspot.fr/2009/04/tcpip-net-sockets-faq.html) to understand the problem.

ChrisW67's example does not use raw TCP sockets but the higher-level QNetworkAccessManager api (supporting http, ftp, etc.); nevertheless it shows how to deal with this "message framing" problem: it splits the incoming byte stream using the two-byte "\n\n" delimiter. Another solution would be to prefix each message with its length (see the FAQ).

ChrisW67
21st August 2012, 07:37
+1 what yeye_olive said.

Just to expand a little. You have no control over exactly how the data you put in one end is broken up for transmission, just that TCP will deliver it all in the correct order. You might get all of one or both lists in the one packet... or you might not. So, you have to handle the worst case as in this contrived example. Let's say your servers sends the following data into the stream:


filename1\nfilename2\nfilename3\n\nanotherset1\nan otherset2\n\n

then the receiver might get bits of data in chunks like this (packet per line):


file
name1\nf
ilename\n
2\nfilename3\n\nanoth
erset1
\nanotherset2\n\n


So, you start with an empty buffer, then:

Packet 1 arrives and you add it to the buffer. There is no end-of-list mark in the buffer so you go back to waiting.
Packet 2 arrives and you add it to the buffer. There is no end-of-list mark in the buffer so you go back to waiting.
Packet 3 arrives and you add it to the buffer. There is no end-of-list mark in the buffer so you go back to waiting.
Packet 4 arrives and you add it to the buffer. There is an end-of-list mark in the buffer so you:

Extract the data from the start of the buffer to the end of list marker and process the complete first list
Remove the processed data from the buffer leaving "anoth" in the buffer
If there is another end-of-list marker in the buffer (possible, but not in this example) then repeat the preceding steps.
Go back to waiting

Packet 5 arrives and you add it to the buffer. There is no end-of-list mark in the buffer so you go back to waiting.
Packet 6 arrives and you add it to the buffer. There is an end-of-list mark in the buffer so you repeat the processing then go back to waiting.


The exact mechanics of the processing are application specific and up to you. You might process a single file name when you see the end-of-line marker or wait for a whole list as I did.

rinku
22nd August 2012, 16:04
Yes i was wrong..thanks for your valuable replies..