Usage of QDataStream in QTcpSocket



  • I want to do a two-way communication between a client and a server.
    In my design, the client first sends out a request message. Then the server reads the request message and response correspondingly. I use multithreading to handle multiple clients, but now I just test on one client connection to the server.
    Now, the client can send out the request message, and the server can read it, but the client never receives the response sent by the server.

    client:

    //...
    //some other codes before
    QTcpSocket tcpsocket;
    tcpsocket.connectToHost(sources[0], fport); 
    // source[0] contains a host address, fport stores the port
    if(!tcpsocket.waitForConnected(5000)){
                qDebug() <<"WaitforConnected fails"<< "TCP Connection fails" << tcpsocket.errorString();
                break;
            }
    QString requestFile(temp.c_str()); //temp is a filename
    QByteArray block;
    QByteArray inblock;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_5_11);
    out << (quint32)0 << requestFile;
    tcpsocket.write(block);
    tcpsocket.flush();
    tcpsocket.waitForBytesWritten();
     //read the server response
    QDataStream in(&tcpsocket);
    in.setVersion(QDataStream::Qt_5_11);
    do {
           if (!tcp.waitForReadyRead(5000)) {
                emit error(tcpsocket.error(), tcpsocket.errorString());
                //get "operation timeout" or "remote host close the connection" here
                break;
           }
          in.startTransaction();
          in >> inblock;
          qDebug() << inblock.size(); //always 0
    } while (!in.commitTransaction());
    //other codes below
    //...
    

    server:

    void ServerThread::run(){
        QTcpSocket tcp;
        //socketDesciptor passed by the override incomingConnection() function in the QTcpServer and pass the  socketDesciptor to a new QThread, then starts the thread 
        if(!tcp.setSocketDescriptor(socketDesciptor)){
            emit error(tcp.error(), tcp.errorString());
            return;
        }
       
    
        QDataStream in(&tcp);
        in.setVersion(QDataStream::Qt_5_11);
        quint32 pos;
        QString filename;
        do {
            if (!tcp.waitForReadyRead(5000)) {
                emit error(tcp.error(), tcp.errorString());
                return;
            }
            in.startTransaction();
            in >> pos >> filename;
            //pos and filename can be successfully read
        } while (!in.commitTransaction());
        
        if(pos == (quint32)0){
            QFile f(filename);
            if(!f.open(QIODevice::ReadOnly)){
                return;
            }
            //send back response to the client
            f.seek(0);
            QByteArray bb = f.read(44);
            qDebug() << tcp.write(bb); //output 44, which is expected
            tcp.waitForBytesWritten();
        }
        else return;
    
    }
    

    I am a newbie in both Qt and tcp, and will appreciate any comments about the codes. Thank you!


  • Moderators

    @Gerrard_queue said in Usage of QDataStream in QTcpSocket:

    if (!tcp.waitForReadyRead(5000)) {

    I would remove this part from server as it would terminate the server when no client connects for 5 seconds. Also it is better to use asynchronous API (signals/slots) instead of blocking calls.
    Also you should connect a slot to http://doc.qt.io/qt-5/qabstractsocket.html#error-1 to see whether there are any errors.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.