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. read and write to qtcpsocket using qdatastream
QtWS25 Last Chance

read and write to qtcpsocket using qdatastream

Scheduled Pinned Locked Moved Unsolved General and Desktop
qtcpsocketqdatastream
3 Posts 3 Posters 11.6k 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.
  • C Offline
    C Offline
    CybeX
    wrote on 7 Feb 2017, 06:21 last edited by
    #1

    There are various methods of reading and writing from a QTcpSocket using a QDatastream as seen here

    The difference is, I will be sending more than "one packet" or blocks.

    A basic implementation on the server (sending) side and client (recieving) is seen below - only the actual sending and receiving snippets are shown

    More Info, What I tried:

    When writing to a QTcpSocket, I attempted to use the QTcpSocket::canReadLine() however this fails straightup after the QTcpSocket::waitForReadReady() signal fires.

    I then tried QDataStream::atEnd() in a while loop which causes a system crash :(

    The code below shows my latest attempt of going through the QDataStream docs, and utilzing the commitTransaction where it states

    If no full packet is received, this code restores the stream to the initial position, after which you need to wait for more data to arrive.

    Under the heading Using Read Transactions. But ofcourse, this just reads one block that is sent, i.e the first block.

    Question:

    When writing to a QTcpSocket multiple times, and flushing the socket each time to send that data, how can I read this from a QTcpSocket as it is send, keep the original "send structure"?

    The example below only reads the first block and ends. I would like to read the block containing "Response 2" and "Response 3".

    Code Implementations:

    //server.h

    //...
    QTcpSocket *clientSocket = nullptr;
    QDataStream in;
    //...
    

    //server.cpp

    //...
    in.setDevice(clientSocket);
    in.setVersion(QDataStream::Qt_4_0);
    
    in.startTransaction();
    
    QString nextFortune;
    in >> nextFortune;
    
    if (in.commitTransaction())
        ui->lblOut->setText(nextFortune);
    
    if (clientSocket != nullptr) {
        if (!clientSocket->isValid()) {
            qDebug() << "tcp socket invalid";
            return;
        }
        if (!clientSocket->isOpen()) {
            qDebug() << "tcp socket not open";
            return;
        }
    
        QByteArray block;
        QDataStream out(&block, QIODevice::WriteOnly);
        out.setVersion(QDataStream::Qt_4_0);
    
        out << QString(QString("Response:") + nextFortune);
        if (!clientSocket->write(block)){
            QMessageBox::information(this, tr("Server"),tr("Could not send message"));
        }
        clientSocket->flush();
    //        block.clear();
    
        out << QString("Response number 2");
        if (!clientSocket->write(block)){
            QMessageBox::information(this, tr("Server"),tr("Could not send message"));
        }
        clientSocket->flush();
    //        block.clear();
    
        out << QString("Response number 3 here, and this is the end!");
        if (!clientSocket->write(block)){
            QMessageBox::information(this, tr("Server"),tr("Could not send message"));
        }
        clientSocket->flush();
        clientSocket->disconnectFromHost();
    
    }
    //...
    

    And the client side

    //client.h

    //...
    QTcpSocket *tcp_con = nullptr;
    QDataStream in;
    //...
    

    //client.cpp

    //...
    if(!tcp_con->waitForReadyRead()){
        qDebug(log_lib_netman_err) << "tcp con timeout for reading";
        tcp_con->disconnectFromHost();
        return ReturnObject(ReturnCode::SocketError, QString());
    }
    
    in.setDevice(tcp_con);
    in.setVersion(QDataStream::Qt_4_0);
    
    in.startTransaction();
    
    QList<QString> data_rcv = QList<QString>();
    QString s;
    
    //    while (tcp_con->canReadLine()) {
    //        in >> s;
    //        data_rcv.push_back(s);
    //    }
    //    while (!in.read) {
    in >> s;
    data_rcv.push_back(s);
    //    }
    
    
    while (!in.commitTransaction()){
        qDebug(log_lib_netman_info) << "waiting for more data";
        in >> s;
        data_rcv.push_back(s);
        //        qDebug(log_lib_netman_err) << "Unable to send data to server";
        //        tcp_con->disconnectFromHost();
        //        return ReturnObject(ReturnCode::FailedReceiving, QString());
    }
    
    //    if (s.isEmpty()) {
    //        qDebug(log_lib_netman_err) << "Empty response recieved";
    //        tcp_con->disconnectFromHost();
    //        return ReturnObject(ReturnCode::NoDataRecieved, QString());
    //    }
    
    tcp_con->disconnectFromHost();
    return ReturnObject(ReturnCode::ReceivedSuccess, data_rcv);
    

    Help would be greatly appreciated!

    K 1 Reply Last reply 7 Feb 2017, 09:52
    0
    • C CybeX
      7 Feb 2017, 06:21

      There are various methods of reading and writing from a QTcpSocket using a QDatastream as seen here

      The difference is, I will be sending more than "one packet" or blocks.

      A basic implementation on the server (sending) side and client (recieving) is seen below - only the actual sending and receiving snippets are shown

      More Info, What I tried:

      When writing to a QTcpSocket, I attempted to use the QTcpSocket::canReadLine() however this fails straightup after the QTcpSocket::waitForReadReady() signal fires.

      I then tried QDataStream::atEnd() in a while loop which causes a system crash :(

      The code below shows my latest attempt of going through the QDataStream docs, and utilzing the commitTransaction where it states

      If no full packet is received, this code restores the stream to the initial position, after which you need to wait for more data to arrive.

      Under the heading Using Read Transactions. But ofcourse, this just reads one block that is sent, i.e the first block.

      Question:

      When writing to a QTcpSocket multiple times, and flushing the socket each time to send that data, how can I read this from a QTcpSocket as it is send, keep the original "send structure"?

      The example below only reads the first block and ends. I would like to read the block containing "Response 2" and "Response 3".

      Code Implementations:

      //server.h

      //...
      QTcpSocket *clientSocket = nullptr;
      QDataStream in;
      //...
      

      //server.cpp

      //...
      in.setDevice(clientSocket);
      in.setVersion(QDataStream::Qt_4_0);
      
      in.startTransaction();
      
      QString nextFortune;
      in >> nextFortune;
      
      if (in.commitTransaction())
          ui->lblOut->setText(nextFortune);
      
      if (clientSocket != nullptr) {
          if (!clientSocket->isValid()) {
              qDebug() << "tcp socket invalid";
              return;
          }
          if (!clientSocket->isOpen()) {
              qDebug() << "tcp socket not open";
              return;
          }
      
          QByteArray block;
          QDataStream out(&block, QIODevice::WriteOnly);
          out.setVersion(QDataStream::Qt_4_0);
      
          out << QString(QString("Response:") + nextFortune);
          if (!clientSocket->write(block)){
              QMessageBox::information(this, tr("Server"),tr("Could not send message"));
          }
          clientSocket->flush();
      //        block.clear();
      
          out << QString("Response number 2");
          if (!clientSocket->write(block)){
              QMessageBox::information(this, tr("Server"),tr("Could not send message"));
          }
          clientSocket->flush();
      //        block.clear();
      
          out << QString("Response number 3 here, and this is the end!");
          if (!clientSocket->write(block)){
              QMessageBox::information(this, tr("Server"),tr("Could not send message"));
          }
          clientSocket->flush();
          clientSocket->disconnectFromHost();
      
      }
      //...
      

      And the client side

      //client.h

      //...
      QTcpSocket *tcp_con = nullptr;
      QDataStream in;
      //...
      

      //client.cpp

      //...
      if(!tcp_con->waitForReadyRead()){
          qDebug(log_lib_netman_err) << "tcp con timeout for reading";
          tcp_con->disconnectFromHost();
          return ReturnObject(ReturnCode::SocketError, QString());
      }
      
      in.setDevice(tcp_con);
      in.setVersion(QDataStream::Qt_4_0);
      
      in.startTransaction();
      
      QList<QString> data_rcv = QList<QString>();
      QString s;
      
      //    while (tcp_con->canReadLine()) {
      //        in >> s;
      //        data_rcv.push_back(s);
      //    }
      //    while (!in.read) {
      in >> s;
      data_rcv.push_back(s);
      //    }
      
      
      while (!in.commitTransaction()){
          qDebug(log_lib_netman_info) << "waiting for more data";
          in >> s;
          data_rcv.push_back(s);
          //        qDebug(log_lib_netman_err) << "Unable to send data to server";
          //        tcp_con->disconnectFromHost();
          //        return ReturnObject(ReturnCode::FailedReceiving, QString());
      }
      
      //    if (s.isEmpty()) {
      //        qDebug(log_lib_netman_err) << "Empty response recieved";
      //        tcp_con->disconnectFromHost();
      //        return ReturnObject(ReturnCode::NoDataRecieved, QString());
      //    }
      
      tcp_con->disconnectFromHost();
      return ReturnObject(ReturnCode::ReceivedSuccess, data_rcv);
      

      Help would be greatly appreciated!

      K Offline
      K Offline
      koahnig
      wrote on 7 Feb 2017, 09:52 last edited by koahnig 2 Jul 2017, 09:53
      #2

      @CybeX said in read and write to qtcpsocket using qdatastream:

      Question:
      When writing to a QTcpSocket multiple times, and flushing the socket each time to send that data, how can I read this from a QTcpSocket as it is send, keep the original "send structure"?
      The example below only reads the first block and ends. I would like to read the block containing "Response 2" and "Response 3".

      A simple No.

      In extreme you can rely only that your sending structure is maintained throughout the process is when you are considering one byte as structure. The readyRead signal may be fired any time when receiving data. It depends on how busy the event loop is, the speed of transfer and the speed of computer.

      A not very reliable option would be to wait long enough before reading the data. However, waitForReadRead does support only waiting for a certain, but it is passed as soon as bytes are received. You need to think about handling this yourself. Typically one is sending the size of the subsequent structure first. So you know at least how many bytes have to be received.

      Vote the answer(s) that helped you to solve your issue(s)

      1 Reply Last reply
      1
      • B Offline
        B Offline
        Boyd
        wrote on 11 Sept 2017, 18:38 last edited by
        #3

        I've posted an answer how to know if you have read everything here: https://stackoverflow.com/a/46162082/969016

        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