Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Data / file transfer via TCP

Data / file transfer via TCP

Scheduled Pinned Locked Moved Solved General and Desktop
16 Posts 8 Posters 19.2k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    Jeff_T69
    wrote on last edited by A Former User
    #1

    Hey there,

    I want to realize a data/file transfer between 2 classes, one client and one server. I allready get an connection using the QT Classes "QTcpServer" "QTcpSocket". And I can send messages using this:

    //code here
    void Server::sendString()  {
    	// send via QByteArray 
    	QByteArray block;
    	QDataStream out(&block, QIODevice::WriteOnly);
    	out.setVersion(QDataStream::Qt_5_5);
    	out << (quint16)0;
    	// create data for the client 
    	QString data;
    	data.append(tr("Just some bla "));
    	out << data;
    	out.device()->seek(0);
    	out << (quint16)(block.size() - sizeof(quint16));
    	// get the next client-connection
    	QTcpSocket *clientConnection =
    		tcpServer->nextPendingConnection();
    	// signal  
    	connect(clientConnection, SIGNAL(disconnected()),
    		clientConnection, SLOT(deleteLater()));
    	// write the string into the socket
    	clientConnection->write(block);
    	// disconnect
    	clientConnection->disconnectFromHost();
    }
    

    now I want to send files. I tried it using class "QFile", but I failed.
    Is my approach right?? How would you do a data/file transfer via TCP?

    thank you for your help.

    greetings
    Thomas

    1 Reply Last reply
    1
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #2

      hi
      It seems fine. If you can send the QString Data, you can send anything you like.
      If you want to send a binary file, then you should never ever convert to string or char *
      as you will only get up till first 0 (zero) it finds.
      so to send say an image: (pseudo code-ish)

      QFile file("c:/mypic.jpg");
      file.open(QIODevice::ReadOnly);
      QByteArray mydata=file.readAll();
      then then clientConnection->write(mydata).
      

      On the receiver end, also read it as QByteArray and
      save to file again.

      QByteArray data;
      // read ...
      QFile file("C:/path/myimage.jpg"); // change path
      file.open(QIODevice::WriteOnly);
      file.write(data);
      file.close();
      
      1 Reply Last reply
      1
      • J Offline
        J Offline
        Jeff_T69
        wrote on last edited by
        #3

        Hi,
        thank you for your help!!
        I tried to implement it, with your advice, but my program just create an empty file.
        There could be a problem with my server class, because I did't understand how I get the bytes in a DataStream.
        I thouht the command file.readAll() reads the whole file and QDataStream puts this into my Socket.
        But now I think it isn't that easy!??

        In my Server Class

        void Server::sendData()  {
        	QFile file("C:/Uploads/test.zip");
        	if (!file.open(QFile::ReadOnly))
        	{
        	ui.label_Server_Status_Header ->setText(
              tr("Could not open the file for reading"));
        		return;
        	}
        	QByteArray mydata = file.readAll();
        	QDataStream out(&mydata, QIODevice::WriteOnly);
        
            out.setVersion(QDataStream::Qt_5_5);
        	out.device()->seek(0); // sets device
        	//out << (quint64) mydata.size();
        	//out << (quint16)0;
        	out << (quint64) mydata.size();  // filesize // mydata or file.size() ???
        	out << mydata;
        
            // get the next client-connection
            QTcpSocket *clientConnection =
                tcpServer->nextPendingConnection();
            // signal  
            connect(clientConnection, SIGNAL(disconnected()),
                clientConnection, SLOT(deleteLater()));
            // write the string into the socket
            clientConnection->write(mydata);
            // disconnect
            clientConnection->disconnectFromHost();
        }
        

        In my Client Class

        // read Servers datas
        void Client::readData() {
        QDataStream in(tcpSocket);
        	in.setVersion(QDataStream::Qt_5_5);
          
        	if (blockSize == 0) {     
        		// data to read available   
        		if ( tcpSocket->bytesAvailable() <         
        			(int)sizeof(quint16) )        
        			return;     
        		in >> blockSize; 
        	} 
        	if (tcpSocket->bytesAvailable() < blockSize)    
        		return;
        
        	QByteArray nextByte;
        	// read ...
        	in >> nextByte;
        	
        	/*if (nextByte == currentByte) {
             QTimer::singleShot(0, this, SLOT(requestNewConnection()));
             return; 
        	}*/
        
        	currentByte = nextByte;
        	QFile file("C:/Downloads/test.zip"); // download path
        	file.open(QIODevice::WriteOnly);
        	file.write(currentByte);
        	file.close();
         
          ui.getTimeButton->setEnabled(true);
        }
        
        
        kshegunovK 1 Reply Last reply
        0
        • mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Hi
          you must use the debugger to find out what went wrong.
          you write the size of the zip file as a header.

          Do you get the size over correctly ?
          Meaning that blockSize is actually mydata.size();
          also after
          in >> nextByte;
          if you
          qDebug() << "bytes read: " << nextByte.size();

          what you get as output?

          1 Reply Last reply
          0
          • M Offline
            M Offline
            mcosta
            wrote on last edited by
            #5

            Hi,

            what do you do in server is

            socket->write(data);
            socket->disconnectFromHost();
            

            IMO is not correct because you should wait that the bytes are written before closing the connection for instance

            socket->write(data);
            // Wait until data are written to the native socket buffer
            socket->waitForBytesWritten();
            socket->disconnectFromHost();
            

            Once your problem is solved don't forget to:

            • Mark the thread as SOLVED using the Topic Tool menu
            • Vote up the answer(s) that helped you to solve the issue

            You can embed images using (http://imgur.com/) or (http://postimage.org/)

            1 Reply Last reply
            3
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by SGaist
              #6

              Hi,

              One other thing:
              You are creating your QDataStream on your file buffer, then you write the block size in place of the first bytes of your file.

              Taking the fortune server examples code, it should be:

              QByteArray block; // Data that will be sent
              QDataStream out(&block, QIODevice::WriteOnly);
              out.setVersion(QDataStream::Qt_5_5);
              out << (quint64)0; // Space for size of data
              out << file.readAll(); // Actual data
              out.device()->seek(0);
              out << (quint64)(block.size() - sizeof(quint64));
              

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • J Jeff_T69

                Hi,
                thank you for your help!!
                I tried to implement it, with your advice, but my program just create an empty file.
                There could be a problem with my server class, because I did't understand how I get the bytes in a DataStream.
                I thouht the command file.readAll() reads the whole file and QDataStream puts this into my Socket.
                But now I think it isn't that easy!??

                In my Server Class

                void Server::sendData()  {
                	QFile file("C:/Uploads/test.zip");
                	if (!file.open(QFile::ReadOnly))
                	{
                	ui.label_Server_Status_Header ->setText(
                      tr("Could not open the file for reading"));
                		return;
                	}
                	QByteArray mydata = file.readAll();
                	QDataStream out(&mydata, QIODevice::WriteOnly);
                
                    out.setVersion(QDataStream::Qt_5_5);
                	out.device()->seek(0); // sets device
                	//out << (quint64) mydata.size();
                	//out << (quint16)0;
                	out << (quint64) mydata.size();  // filesize // mydata or file.size() ???
                	out << mydata;
                
                    // get the next client-connection
                    QTcpSocket *clientConnection =
                        tcpServer->nextPendingConnection();
                    // signal  
                    connect(clientConnection, SIGNAL(disconnected()),
                        clientConnection, SLOT(deleteLater()));
                    // write the string into the socket
                    clientConnection->write(mydata);
                    // disconnect
                    clientConnection->disconnectFromHost();
                }
                

                In my Client Class

                // read Servers datas
                void Client::readData() {
                QDataStream in(tcpSocket);
                	in.setVersion(QDataStream::Qt_5_5);
                  
                	if (blockSize == 0) {     
                		// data to read available   
                		if ( tcpSocket->bytesAvailable() <         
                			(int)sizeof(quint16) )        
                			return;     
                		in >> blockSize; 
                	} 
                	if (tcpSocket->bytesAvailable() < blockSize)    
                		return;
                
                	QByteArray nextByte;
                	// read ...
                	in >> nextByte;
                	
                	/*if (nextByte == currentByte) {
                     QTimer::singleShot(0, this, SLOT(requestNewConnection()));
                     return; 
                	}*/
                
                	currentByte = nextByte;
                	QFile file("C:/Downloads/test.zip"); // download path
                	file.open(QIODevice::WriteOnly);
                	file.write(currentByte);
                	file.close();
                 
                  ui.getTimeButton->setEnabled(true);
                }
                
                
                kshegunovK Offline
                kshegunovK Offline
                kshegunov
                Moderators
                wrote on last edited by kshegunov
                #7

                @Jeff_T69
                Hello,

                This part:

                    QByteArray mydata = file.readAll();
                    QDataStream out(&mydata, QIODevice::WriteOnly);
                
                    out.setVersion(QDataStream::Qt_5_5);
                    out.device()->seek(0); // sets device
                    //out << (quint64) mydata.size();
                    //out << (quint16)0;
                    out << (quint64) mydata.size();  // filesize // mydata or file.size() ???
                    out << mydata;
                

                looks very suspicious. I don't get it. You read the file, then create a data stream attached to the buffer containing the file and then write it over with the << operator? What exactly is it that this part of the code is trying to achieve?
                I believe simply doing this is sufficient:

                QTcpSocket * socket = tcpServer->nextPendingConnection();
                socket->write(mydata);
                if (!socket->waitForBytesWritten())
                     ; // Some error occured
                socket->disconnectFromHost();
                

                Similarly on the client side:

                if (tcpSocket->bytesAvailable() <= 0)
                    return;
                
                while (tcpSocket->state() == QAbstractSocket::ConnectedState)  {
                    tcpSocket->waitForReadyRead();
                    file.write(tcpSocket->read(tcpSocket->bytesAvailable()));
                }
                

                Additionally, don't open the file at every read, just open it once and then write. The way you're doing it, the file contents will always be overwritten on each subsequent call.

                Kind regards.

                EDIT:
                It seems @SGaist beat me to it and posted while I was writing. I see now what the idea of the first part of the code is.

                Read and abide by the Qt Code of Conduct

                1 Reply Last reply
                0
                • J Offline
                  J Offline
                  Jeff_T69
                  wrote on last edited by
                  #8

                  Thank you very much for all your replies. I see what went wrong.
                  Now it works very well.

                  Server Class

                  void Server::sendData()  {
                  	QFile file("C:/Uploads/Test.zip");
                  	
                  	if (!file.open(QFile::ReadOnly))
                  	{
                  	ui.label_Server_Status_Header ->setText(
                        tr("Could not open the file for reading"));
                  		return;
                  	}
                  
                  	QByteArray block; // Data that will be sent
                  	QDataStream out(&block, QIODevice::WriteOnly);
                  	out.setVersion(QDataStream::Qt_5_5);
                  	out << (quint64)0; // Space for size of data
                  	out << file.readAll(); // Actual data
                  	out.device()->seek(0);
                  	out << (quint64)(block.size() - sizeof(quint64));
                  
                      // get the next client-connection
                      QTcpSocket *clientConnection =
                          tcpServer->nextPendingConnection();
                      // signal  
                      connect(clientConnection, SIGNAL(disconnected()),
                          clientConnection, SLOT(deleteLater()));
                      // write the string into the socket
                      clientConnection->write(block);
                  	// Wait until data are written to the native socket buffer
                  	clientConnection->waitForBytesWritten();
                      // disconnect
                      clientConnection->disconnectFromHost();
                  }
                  

                  Client Class

                  // read Servers datas
                  void Client::readData() {
                  QDataStream in(tcpSocket);
                  	in.setVersion(QDataStream::Qt_5_5);
                    
                  	if (blockSize == 0) {     
                  		// data to read available   
                  		if ( tcpSocket->bytesAvailable() <         
                  			(int)sizeof(quint16) )        
                  			return;     
                  		in >> blockSize; 
                  	} 
                  	if (tcpSocket->bytesAvailable() < blockSize)    
                  		return;
                  
                  	QByteArray nextByte;
                  	// read
                  	in >> nextByte;
                  
                  	currentByte = nextByte;
                  	QFile file("C:/Downloads/Test.zip"); // download path
                  	
                  	file.open(QIODevice::WriteOnly);
                  	file.write(currentByte);
                  	file.close();
                   
                    ui.getTimeButton->setEnabled(true);
                  }
                  
                  T 1 Reply Last reply
                  1
                  • K Offline
                    K Offline
                    karti gesar
                    wrote on last edited by
                    #9

                    hi all,
                    If file size is 1000 kb it is possible to send all the data

                    VRoninV 1 Reply Last reply
                    0
                    • K karti gesar

                      hi all,
                      If file size is 1000 kb it is possible to send all the data

                      VRoninV Offline
                      VRoninV Offline
                      VRonin
                      wrote on last edited by VRonin
                      #10

                      @karti-gesar yes, of course

                      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                      ~Napoleon Bonaparte

                      On a crusade to banish setIndexWidget() from the holy land of Qt

                      K 1 Reply Last reply
                      0
                      • VRoninV VRonin

                        @karti-gesar yes, of course

                        K Offline
                        K Offline
                        karti gesar
                        wrote on last edited by VRonin
                        #11

                        @VRonin

                        QFile file("D:/serial_Data.txt");
                            file.open(QIODevice::ReadOnly);
                            QByteArray mydata=file.readAll();
                             socket->write(mydata);
                        //Serial_Data file size is 1072kb but only 1 kb is writting
                        
                        1 Reply Last reply
                        0
                        • VRoninV Offline
                          VRoninV Offline
                          VRonin
                          wrote on last edited by VRonin
                          #12

                          add socket->waitForBytesWritten(-1);

                          P.S.
                          Since your file is a text file probably what you are reading is not what you want and/or it's not solid to change. you should use:

                          QFile file("D:/serial_Data.txt");
                          if(file.open(QIODevice::ReadOnly | QIODevice::Text)){
                          const auto mydata=QTextStream(&file).readAll();
                          QDataStream socketStream(socket);
                          socketStream << mydata;
                          socket->waitForBytesWritten(-1);
                          }
                          

                          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                          ~Napoleon Bonaparte

                          On a crusade to banish setIndexWidget() from the holy land of Qt

                          1 Reply Last reply
                          2
                          • K Offline
                            K Offline
                            karti gesar
                            wrote on last edited by
                            #13

                            k i will try

                            1 Reply Last reply
                            0
                            • K Offline
                              K Offline
                              karti gesar
                              wrote on last edited by VRonin
                              #14
                              QFile file("D:/serial_Data.txt");
                               if(file.open(QIODevice::ReadOnly| QIODevice::Text))
                                 {
                                      const auto mydata=QTextStream(&file).readAll();
                                     QDataStream socketStream(socket);
                                     socketStream << mydata;
                                     socket->waitForBytesWritten(-1);
                                   qDebug()<<mydata.constData();
                                 }
                              

                              this what i used....for file size smaller it's working ..for huge file size it not writing

                              VRoninV 1 Reply Last reply
                              0
                              • K karti gesar
                                QFile file("D:/serial_Data.txt");
                                 if(file.open(QIODevice::ReadOnly| QIODevice::Text))
                                   {
                                        const auto mydata=QTextStream(&file).readAll();
                                       QDataStream socketStream(socket);
                                       socketStream << mydata;
                                       socket->waitForBytesWritten(-1);
                                     qDebug()<<mydata.constData();
                                   }
                                

                                this what i used....for file size smaller it's working ..for huge file size it not writing

                                VRoninV Offline
                                VRoninV Offline
                                VRonin
                                wrote on last edited by VRonin
                                #15

                                @karti-gesar said in data/ file transfer via TCP:

                                huge

                                You should define huge but in this case you can use:

                                QFile file("D:/serial_Data.txt");
                                if(file.open(QIODevice::ReadOnly | QIODevice::Text)){
                                QDataStream socketStream(socket);
                                QTextStream fileStream(&file);
                                for(QString mydata=fileStream.readLine();!mydata.isEmpty();mydata=fileStream.readLine())
                                socketStream << mydata;
                                socket->waitForBytesWritten(-1);
                                }
                                

                                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                ~Napoleon Bonaparte

                                On a crusade to banish setIndexWidget() from the holy land of Qt

                                1 Reply Last reply
                                4
                                • J Jeff_T69

                                  Thank you very much for all your replies. I see what went wrong.
                                  Now it works very well.

                                  Server Class

                                  void Server::sendData()  {
                                  	QFile file("C:/Uploads/Test.zip");
                                  	
                                  	if (!file.open(QFile::ReadOnly))
                                  	{
                                  	ui.label_Server_Status_Header ->setText(
                                        tr("Could not open the file for reading"));
                                  		return;
                                  	}
                                  
                                  	QByteArray block; // Data that will be sent
                                  	QDataStream out(&block, QIODevice::WriteOnly);
                                  	out.setVersion(QDataStream::Qt_5_5);
                                  	out << (quint64)0; // Space for size of data
                                  	out << file.readAll(); // Actual data
                                  	out.device()->seek(0);
                                  	out << (quint64)(block.size() - sizeof(quint64));
                                  
                                      // get the next client-connection
                                      QTcpSocket *clientConnection =
                                          tcpServer->nextPendingConnection();
                                      // signal  
                                      connect(clientConnection, SIGNAL(disconnected()),
                                          clientConnection, SLOT(deleteLater()));
                                      // write the string into the socket
                                      clientConnection->write(block);
                                  	// Wait until data are written to the native socket buffer
                                  	clientConnection->waitForBytesWritten();
                                      // disconnect
                                      clientConnection->disconnectFromHost();
                                  }
                                  

                                  Client Class

                                  // read Servers datas
                                  void Client::readData() {
                                  QDataStream in(tcpSocket);
                                  	in.setVersion(QDataStream::Qt_5_5);
                                    
                                  	if (blockSize == 0) {     
                                  		// data to read available   
                                  		if ( tcpSocket->bytesAvailable() <         
                                  			(int)sizeof(quint16) )        
                                  			return;     
                                  		in >> blockSize; 
                                  	} 
                                  	if (tcpSocket->bytesAvailable() < blockSize)    
                                  		return;
                                  
                                  	QByteArray nextByte;
                                  	// read
                                  	in >> nextByte;
                                  
                                  	currentByte = nextByte;
                                  	QFile file("C:/Downloads/Test.zip"); // download path
                                  	
                                  	file.open(QIODevice::WriteOnly);
                                  	file.write(currentByte);
                                  	file.close();
                                   
                                    ui.getTimeButton->setEnabled(true);
                                  }
                                  
                                  T Offline
                                  T Offline
                                  Talha Celik
                                  wrote on last edited by
                                  #16

                                  @Jeff_T69 what is block size ?

                                  1 Reply Last reply
                                  0

                                  • Login

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • Users
                                  • Groups
                                  • Search
                                  • Get Qt Extensions
                                  • Unsolved