Unsolved Estimate file transfer code via QTcpSocket
-
Hello.
It was required to do file transfer through QTcpSocket. Googled many different options that confused me.
The first method was done through the transmission of the length of the block and then the block itself. But then I found a more advanced way through transactions, which appeared in Qt 5.7. I did it on it, asynchronously.
Please rate whether it is correctly and how much correctly done? If there are any comments, I will be glad to know them. Thank.I pass in several variables:
- type of network packet (file, message or other)
If the file is: - file name
- file size in bytes
- data block
- and at the end a text message
File Transfer Code:
enum PacketType { TYPE_NONE = 0, TYPE_MSG = 1, TYPE_FILE = 2, }; void TcpClient::socketSendMessage() { QDataStream stream(m_pTcpSocket); stream.setVersion(QDataStream::Qt_DefaultCompiledVersion); stream << PacketType::TYPE_FILE; QString fileName("/mnt/d/1.png"); QFile file(fileName); QFileInfo fileInfo(file); qint64 fileSize = fileInfo.size(); stream << fileName; stream << fileSize; int countSend = 0; if (file.open(QFile::ReadOnly)) { while(!file.atEnd()) { QByteArray data = file.read(32768*8); stream << data; countSend++; } qDebug() << Tools::getTime() << "_CLIENT: ------------------------ countSend FINAL: " << countSend; } file.close(); qDebug() << Tools::getTime() << "_CLIENT: send file ok"; QString testStr("TEST_MESSAGE"); stream << testStr; }
File retrieval code:
Header file server:#ifndef MYTCPSERVER_H #define MYTCPSERVER_H #include <QObject> #include <QTcpServer> #include <QTcpSocket> #include "global.h" #include <QFile> class MyTcpServer : public QObject { Q_OBJECT public: explicit MyTcpServer(QObject *parent = nullptr); ~MyTcpServer(); int number; QString str; public slots: void slotNewConnection(); void slotServerRead(); void slotClientDisconnected(); void onSocketReceiveMessage(); void startServer(); private: QTcpServer * mTcpServer; QTcpSocket * mTcpSocket; qint64 sizeReceivedData; QString fileCopy; PacketType packetType; QString filePath; qint64 fileSize; QString testStr; QByteArray tmpBlock; int countSend; bool receiveFile(QDataStream &stream); }; #endif // MYTCPSERVER_H
In the server constructor:
packetType = PacketType::TYPE_NONE; filePath.clear(); fileSize = 0; testStr.clear(); sizeReceivedData = 0; tmpBlock.clear(); countSend = 0;
Message receiving slot:
void MyTcpServer::onSocketReceiveMessage() { if (!mTcpSocket || !mTcpSocket->bytesAvailable()) return; qDebug() << Tools::getTime() << "SERVER: --------------------new-----------------------"; qDebug() << Tools::getTime() << "SERVER: onSocketReceiveMessage: bytesAvailable" << mTcpSocket->bytesAvailable(); QDataStream stream(mTcpSocket); stream.setVersion(QDataStream::Qt_DefaultCompiledVersion); // Getting PacketType if (packetType == PacketType::TYPE_NONE) { stream.startTransaction(); stream >> packetType; if (!stream.commitTransaction()) { qDebug() << Tools::getTime() << "SERVER: packetType - FAIL commitTransaction"; return; } qDebug() << Tools::getTime() << "SERVER: type:" << packetType; } if (packetType == PacketType::TYPE_MSG) { // } else if (packetType == PacketType::TYPE_FILE) { //==================================================== // Getting filePath if (filePath.isEmpty()) { stream.startTransaction(); stream >> filePath; if (!stream.commitTransaction()) { qDebug() << Tools::getTime() << "SERVER: filePath - FAIL commitTransaction"; return; } qDebug() << Tools::getTime() << "SERVER filePath:" << filePath; } //==================================================== // Getting fileSize if (!fileSize) { stream.startTransaction(); stream >> fileSize; if (!stream.commitTransaction()) { qDebug() << Tools::getTime() << "SERVER: fileSize - FAIL commitTransaction"; return; } qDebug() << Tools::getTime() << "SERVER: fileSize:" << fileSize; } //==================================================== // Getting file if (sizeReceivedData != fileSize) { filePath = this->fileCopy; // temp replace file name QFile file(filePath); file.open(QFile::Append); // Work with the file in the loop "while there is data in the socket" while (!mTcpSocket->atEnd()) { //==================================================== // Getting tmpBlock stream.startTransaction(); stream >> tmpBlock; if (!stream.commitTransaction()) { qDebug() << Tools::getTime() << "SERVER: tmpBlock - FAIL commitTransaction"; break; } qint64 toFile = file.write(tmpBlock); sizeReceivedData += toFile; countSend++; tmpBlock.clear(); if (sizeReceivedData == fileSize) break; } // while (!mTcpSocket->atEnd()) file.close(); } // if (sizeReceivedData != fileSize) if (sizeReceivedData != fileSize) return; qDebug() << Tools::getTime() << "SERVER: sizeReceivedData END: " << sizeReceivedData; qDebug() << Tools::getTime() << "SERVER fileSize ORIG:" << fileSize; qDebug() << "SERVER: countSend FINAL: " << countSend; //==================================================== // Getting testStr if (testStr.isEmpty()) { stream.startTransaction(); stream >> testStr; if (!stream.commitTransaction()) { qDebug() << Tools::getTime() << "SERVER: testStr - FAIL commitTransaction"; return; } qDebug() << Tools::getTime() << "SERVER: testStr:" << testStr; } qDebug() << Tools::getTime() << "SERVER: END - bytesAvailable:" << mTcpSocket->bytesAvailable(); // Clear vars filePath.clear(); fileSize = 0; tmpBlock.clear(); sizeReceivedData = 0; testStr.clear(); countSend = 0; } // else if (packetType == PacketType::TYPE_FILE) }
- type of network packet (file, message or other)
-
@vebmaster You should first explain your use case: what are you trying to implement? File transfer over network?
-
A bit overengineeraed if you ask me but it works.
File transfer doesn't really require processing is just piping raw bytes from one end to the other and you know the file size upfront so you can go useread()
andwrite()
on the device directly without using streams but it's not material -
@jsulm said in Estimate file transfer code via QTcpSocket:
@vebmaster You should first explain your use case: what are you trying to implement? File transfer over network?
Yes.
It was required to do file transfer through QTcpSocket.