Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How a server can send a message to all of the clients (threads)?



  • Hello,

    I work on a sever-client project where the server should support multiple clients. Therefore, I used QThread to create a thread for each of the clients. The server works properly and it can handle the clients. For example, it can echo the received data from clientX to clientX.

    However, I want the server to echo the received message from one of the clients to all of them. For this objective, I make the list of clients with QVector and try to send the message to all (like bellow):

    // In the serverSocketClass:
    void serverSocketClass::incomingConnection(qintptr socketDescriptor) {
    clientSocketClass *thread = new clientSocketClass(socketDescriptor, this);
    mThreads.push_back(thread); // Here I make the list of clients.
    thread->start();
    }

    //In the clientSocketClass:

    void clientSocketClass::readyReadSlot()
    {
    QByteArray Data = clientSocket->readAll();
    for (int i =0;i<cmThreads.length();i++) {
    mThreads[i]->write(Data);
    }
    }

    But, I face with one of the following errors:

    1. If first client connect and do not send any messages and then second client connect and send a message:

    QObject: Cannot create children for a parent that is in a different thread.
    (Parent is QNativeSocketEngine(0x7f2f20002ef0), parent's thread is clientSocketClass(0x5628b63a6f50), current thread is clientSocketClass(0x7f2f4c005620)

    1. If first client connect and send a message then second client connect and send a message:

    QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread

    I hope I could explain the situation well.


  • Qt Champions 2019

    @Bamshad said in How a server can send a message to all of the clients (threads)?:

    mThreads[i]->write(Data);

    Don't do this! You're accessing clients which live in other threads!
    Emit a signal from the thread which wants to broadcast to other clients. All clients should connect to this signal and send the data from their slot.


  • Qt Champions 2017



  • @jsulm In C I use something like this:

    for (int j=serverFd+1; j<=fdMax; j++) {
    send(j,receiveData,strlen(receiveData), 0))
    }

    Because socket descriptor is one of the arguments of send(), I can send the data where I want. But, here wirte() has not any argument except the data. So, how we can tell it to send the data to other sockets?


  • Lifetime Qt Champion

    @Bamshad said in How a server can send a message to all of the clients (threads)?:

    So, how we can tell it to send the data to other sockets?

    By using Signals & Slots, as pointed out by @jsulm and @kshegunov already. You can add arbitrary parameters to a signal and evaluate from the slot.

    Regards



  • @aha_1980 Hi, As far as I understood the signal should emits from the readyReadSlot() of the clinetSocketClass. But, where should be the receiver slot that sends the data to all? I have two class:

    1. serverSocketClass where I create the threads.
    2. clientSocketClass where have the run() function and create the new QTcpSocket.

    In both of them, when I want to send to all I receive the following error:

    QObject: Cannot create children for a parent that is in a different thread.
    (Parent is QNativeSocketEngine(0x7f2f20002ef0), parent's thread is clientSocketClass(0x5628b63a6f50), current thread is clientSocketClass(0x7f2f4c005620)

    So, where is the place for function sendToAll()?


  • Qt Champions 2019

    @Bamshad said in How a server can send a message to all of the clients (threads)?:

    So, where is the place for function sendToAll()?

    Nowhere. It should be a slot. You connect a signal to that slot using queued connection type.
    Instead of calling sendToAll() directly on objects which are in OTHER threads you emit a signal and then Qt will take care to call all connected slots in their threads.

    You should really take a look at the example @kshegunov gave you...


Log in to reply