PDA

View Full Version : saving data to server through QTcpSocket



toufic.dbouk
5th January 2013, 22:31
void myClient::readyRead()
{
//qDebug() << socket->readAll();
QString fPath("location");

QByteArray block=socket->readAll();
QString fName= QString(block);
QFile sentFile(fPath +QDir::separator() + fName);

if(!sentFile.exists())
{
sentFile.open(QFile::WriteOnly);//check if size equal to size or overwrite
while(socket->waitForReadyRead())
{
QByteArray block= socket->readAll();
qDebug()<< "read: " << block.size();
sentFile.write(block);
block.clear();
}
socket->close();
sentFile.close();
}
}

i guess the while loop is blocking my GUI
how can l make this code non-Blocking
Thanks and best regards.

ChrisW67
6th January 2013, 06:42
You do it by opening the receiving file before the transfer, writing all available bytes into that file on each call (of many) your readyRead() handler receives, and closing the file when the finished signal is received. If the files are guaranteed to be small, i.e. not exhaust memory, then you can simply wait for the finished() signal, check for errors, and read the entire file in one hit. No loops required.

You are also making the serious mistake of assuming that the file name arrives in one block that is exactly the size of the string you were expecting. This will almost never be the case and certainly cannot be relied on. You need a smarter protocol.

toufic.dbouk
6th January 2013, 10:35
ohh i see what u mean , thanks.
can you tell me of a way to send the file name as one block followed by another block for the file size
such that these two block will always be in just 2 blocks so that i can receive them knowing the first is the file name and the second is the file size ?
can i add a separator after each like (*^) and then split at the receivers side ?

ChrisW67
6th January 2013, 21:48
can you tell me of a way to send the file name as one block followed by another block for the file size
such that these two block will always be in just 2 blocks so that i can receive them knowing the first is the file name and the second is the file size ?
No, I cannot because that is not how the network works. The only guarantee that TCP provides is that bytes transmitted will be received in the correct order: under the covers it is ensuring order, splitting/joining blocks for network hops that can only handle small/certain packet sizes, and requesting retransmission of blocks that have been corrupted or lost (both reasonably frequent events).

You need to send sufficient information, or define your protocol in such a way, that the receiver can determine/know the number of bytes in the file name. Typically this would be done by:

First sending 1, 2 or 4 bytes (watch byte order issues) indicating the number of bytes in the following file name, then sending the file name, then the file content. The receiver has several states: wait for size bytes, wait for file name, and read data.
Defining a header that has either a known length or a known pattern of terminating bytes so you can detect the end of header/start of data.

There is more ways to do this: FTP uses a separate socket to send control information like file names, HTTP uses a Content-Disposition header to send the file name on a set of headers terminated by two CR LF pairs.