Only a part of File gets send with QtcpSocket
-
Hello Everyone,
I'm having a very curious case trying to send Data with QTcpSocket from a Client to a Server.
I try to send the file Name and the Path where it should be saved on the Server Side. My Code works only for Data under 10 Ko. As soon as the File size is bigger than 10Ko only a part gets sent (14 or 12 Ko).Here's a part of the sender/Client Code:
QFileInfo fileInfo(File); out << Name; out << QString::number(fileInfo.size()); QString FilePath = fileInfo.absolutePath(); printf(FilePath.toStdString().c_str()); out << FilePath; int size = 0; while (!File.atEnd()) { QByteArray rawFile; rawFile = File.read(1000); QFileInfo rawFileInfo(rawFile); size += rawFileInfo.size(); out << rawFile; }On the Server Side
QDataStream in(m_socket); QByteArray z; QString fileName; QString fileSize; QString FilePath; in >> fileName; qDebug() << fileName; in >> fileSize; qDebug() << fileSize; in >> FilePath; QDir Projectpath; Projectpath.mkpath(FilePath); QFile Target(FilePath + "/" + fileName); if (Target.open(QIODevice::Append)) { while (m_socket->bytesAvailable()) { in >> z; Target.write(z); } Target.close(); }The Server creates the directory and saves the File to the right path. I can't understand why it sends only a part of the File and why it works only for files under 10 ko?
PS: qDebug()<< fileSize prints the right size of the File on the Server side. I just can't seem to write all of it to the File.
I'm really desperate and any hint is highly appreciated. Thank you all !
-
Basically it's your responsibility to check how much data you processed
from https://wiki.qt.io/WIP-How_to_create_a_simple_chat_application
The
onReadyReadslot is really the most interesting one. The first thing to remember is that when we receive thereadyReadwe can't make any assumption on how much data is available, the signal only tells us some data is there hence there are 4 cases we need to handle:- The socket did not receive enough data to be a complete message, we only received a partial
- There is exactly enough data in the socket buffer to read a message
- There is more than enough data in the socket buffer to read a message but not enough to read 2 messages
4. There is enough data in the socket buffer to read multiple messages
Cases 1 and 2 are entirely handled by
socketStream.commitTransaction(). If there was not enough data to complete the reading when we calledsocketStream >> jsonData;this method will return false and we'll just exit the function and wait for more data to come in otherwise it will proceed and parse the data as a complete JSON message. Cases 3 and 4 are handled by the infinite loop. After we read the first message we try to read another one in the same way as before and break the loop only when the data in the buffer is no longer enough to be a complete JSON message.To facilitate the handling of differences in the expected size of the data received and the actual size, since Qt 5.7,
QIODeviceandQDataStreamintroduced transactions. Transactions work very similarly to SQL transactions: start the transaction, try and do something with the data, if everything went as expected you commit the transaction, otherwise you can go back as if you did nothing at all.QDataStream::commitTransactionwill actually rollback if it detects there was an error and return false. We use this to check ifsocketStream >> jsonData;retrieved a full JSON document or not.". InternallysocketStream >> jsonData;will read a 32bit unsigned integer that will bejsonData.size()after the read. Then it will read raw bytes of data to fill that length. If it detects any error it will setsocketStream.status()to something different formQDataStream::Ok.socketStream.commitTransaction()then checks that status. If it isQDataStream::Okit will shorten the buffer in the socket by the amount of data we successfully read and return true, otherwise it will return false maintaining the socket buffer identical to what it was before.