keelerjr12
keelerjr12

Reputation: 1943

Implementing a TCP Server

Can anyone tell me if I'm doing this right?

Using Qt I'm implementing a TCP Server by inheriting from the QTcpServer class. On an incoming connection I create a new thread, a new Worker object, and I move the object to the new thread and start the thread. From here, the server keeps listening for new clients and each thread then is in its run method for object Worker.

Now, I create a timer because I need to send updates to each client based on 1 second intervals AND when a song is playing. In the readyRead slot I read data using readAll and then perform some work and send a reply.

However, when I go back to my run method I need to just continue sending song data updates to the clients (with no response from the client). Should this all just go in a while(true) loop and then I check some boolean to start and stop the timer? The track information I need to send is the song progression time.

I guess my question is, should I be doing it this way? It seems a little complex, but then again that's concurrency for you. Basically I need the TCP server to send data to the client repeatedly when some condition is true. I feel like just an endless while loop that checks when to start and stop the timer is useless work.

Would posting code make this clearer?

Upvotes: 1

Views: 793

Answers (1)

Spiek
Spiek

Reputation: 209

This question is a very old one, but perhaps it could still help.

About threads in Qt:
Many people think about parallel processing in Qt like in .NET where you need for every operation another thread, in qt this is not necessary!
In qt you only need a thread if you have blocking code like calculating big things or waiting syncron for an answer from a SQLServer

If i have understand you correctly you don't have such a blocking operation.
So i have programmed a very small TcpServer without inheriting and without a single thread (except the main eventloop thread of course), which hopefully solves your problem and help others:

#include <QObject>
#include <QSet>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>

class TcpServer : public QObject
{
    Q_OBJECT
    public:
        TcpServer()
        {
            // handle new connections
            this->connect(&this->serverTcp, &QTcpServer::newConnection, this, &TcpServer::handleClientConnect);

            // init client refresh timer
            this->timer.setInterval(1000);
            this->connect(&this->timer, &QTimer::timeout, this, &TcpServer::handleClientUpdates);
            this->timer.start();
        }

        bool startListen(qint16 port)
        {
            return this->serverTcp.listen(QHostAddress::Any, port);
        }

    private slots:
        void handleClientConnect()
        {
            QTcpSocket* socketClient = *this->setConnectedClients.insert(this->serverTcp.nextPendingConnection());
            this->connect(socketClient, &QTcpSocket::disconnected, this, &TcpServer::handleClientDisconnect);
            this->connect(socketClient, &QTcpSocket::readyRead, this, &TcpServer::handleClientData);
        }

        void handleClientDisconnect()
        {
            this->setConnectedClients.remove((QTcpSocket*)this->sender());
        }

        void handleClientData()
        {
            QTcpSocket* socketSender = (QTcpSocket*)this->sender();
            // handle here the data sent by the client
        }

        void handleClientUpdates()
        {
            // construct here your update data
            QByteArray baUpdateResponse = "test";

            // send update data to all connected clients
            foreach(QTcpSocket* socketClient, this->setConnectedClients) {
                socketClient->write(baUpdateResponse);
            }
        }

    private:
        QTcpServer serverTcp;
        QTimer timer;
        QSet<QTcpSocket*> setConnectedClients;
};

Upvotes: 1

Related Questions