Unsolved 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:
- 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)- 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.
-
@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. -
-
@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?
-
@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:
- serverSocketClass where I create the threads.
- 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()?
-
@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...