2

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!

Community
  • 1
  • 1
CybeX
  • 2,060
  • 3
  • 48
  • 115
  • This should be useful [Fortune Client Example](http://doc.qt.io/qt-5/qtnetwork-fortuneclient-example.html) – Vladimir Bershov Feb 07 '17 at 07:10
  • @VladimirBershov Hi, this is based on the fortune client server, i created an example of my own, extracting the relevant code for sending and recieving. From this, I implemented it into my current application. the fortune client/server example only sends one "message"/block. My question relates to, how am I able to loop over a list, writing to the socket on each loop iteration and read this from the client side, as it is sent. As seen in the above code, I attempted this without success (client.cpp) – CybeX Feb 07 '17 at 07:38

0 Answers0