Solved what is the significance of qintptr socket() in QSocketNotifier class?
-
I don't think so and also don't understand why it should be needed.
-
@Christian-Ehrlicher
I have created a server client chat program
I'm connecting multiple clients in one thread and i'm using worker thread for reading and writing. Now in worker thread reading is done smoothly but when it comes to writing (means QTcpSocket->write();) i'm getting notification of 'Socket Notifier cannot be enabled or disabled from other thread.' So I'm trying to do QSocketNotifier::setEnabled(); in that worker thread.
So any suggestion on that ? -
@MokJ You can use QTcpSocket only from one thread. That means, you have the read and write functions in the same thread.
From your error description, it seems that is not the case for your program.
-
Thank you @aha_1980
I'm doing reading and writing in the same thread.
Problem is, while writing above said notification pops up.
I'm creating QTcpSocket in different thread which is main thread of the server. -
And this is exactly what the message tells you. This is not allowed. You can overwrite QTcpServer::incomingConnection() , pass the fd to the other thread and create a QTcpSocket there.
-
@Christian-Ehrlicher
If I create QTcpSocket in other thread, it means if I have 100 clients I'd be using 100 threads and there comes another problem. I can't have 100 threads. I want to do all the functioning with just 3 threads. Right now I'm creating sockets in main thread where I have over ridden the QTcpServer::incomingConnection(qintptr descriptor);.
I have connected readyRead() of the QTcpSocket to myserver's readData() slot.
and here in this slot I'm creating a new thread for reading and writing. Is it possible for me to do so without notification ?
And what happens when one socket is sending message to another ?? -
@MokJ said in what is the significance of qintptr socket() in QSocketNotifier class?:
If I create QTcpSocket in other thread, it means if I have 100 clients I'd be using 100 threads and there comes another problem.
No it doesn't. It means you have to create the socket object in the correct thread - the one that will be doing the reading and writing.
I can't have 100 threads. I want to do all the functioning with just 3 threads.
Did you adapt my proposed snippet in your other thread?
Right now I'm creating sockets in main thread where I have over ridden the QTcpServer::incomingConnection(qintptr descriptor);.
Which is wrong. Read the documentation. It's clearly stated that the socket object must be created in the correct thread. As a matter of fact it is the whole purpose of existing for
QTcpServer::incomingConnection
- it gives you the socket descriptor, so you can create theQTcpSocket
object in the correct thread. Creating the socket object in the main thread means you agree that reading and writing will be done from the main thread, thus you get the messages you get - you break that contract and Qt rightfully complains about it!Is it possible for me to do so without notification ?
Implement threaded sockets correctly and you won't get the warning.
And what happens when one socket is sending message to another ??
Eh? I don't understand the question.
-
@kshegunov
yes I have implemented the worker class according to your proposed snippet , and I'm really thankful for that. But I'm not getting how QMetaObject::invokeMethod is working !And what happens when one socket is sending message to another ??
Eh? I don't understand the question.
I mean one clientsocket to other clientsocket , just like a chat application . If we're sending a message from one clientsocket to another , the chances of getting the warning abot QSocketNotifier are always there ! I mean I've just stated to clear my basics now so a bit confused about things.
-
@MokJ said in what is the significance of qintptr socket() in QSocketNotifier class?:
But I'm not getting how QMetaObject::invokeMethod is working !
Well, did you read the documentation about it? Qt has the best documentation of a software product I have ever seen in my 10+ years of coding. Many of the topics in the forums could be resolved by simple searches for the examples or the classes' reference documentation.
If we're sending a message from one clientsocket to another , the chances of getting the warning abot QSocketNotifier are always there ! I mean I've just stated to clear my basics now so a bit confused about things.
If you use signals and slots, you will never get that notification. If you directly call a method from different threads, then you have a race condition and yes you probably will get that warning.
-
@kshegunov I've been reading the document so I might come back after a few hours with questions , I've got one more question for now....
I've done QByteArray B=socket->readAll(); . Now I have to send this B to the destined socket let say socket123, where should I connect the signal BytesWritten(64) to the appropriate slot?
cause till now what I've been doing is, once I get B, the next line of code would be doing QTcpSocket->write(B.toSTDstring().c_str());
and maybe that could be the reason of the socket being in the different thread. -
@MokJ said in what is the significance of qintptr socket() in QSocketNotifier class?:
Now I have to send this B to the destined socket let say socket123, where should I connect the signal BytesWritten(64) to the appropriate slot?
I don't know what your implementation is, what signals or slots you defined, so I can't say. In any case the
connect
is ordinarily done wherever it's convenient to you, usually meaning where you hold references to the two objects you're connecting. It is not unusual this to be the constructor of some class. -
void Worker::readData(){ QTcpSocket *sock=(QTcpSocket*)sender(); QByteArray Message= sock->readAll(); qDebug()<<"Message "<<Message; for(int i=0;i<clientSocketVector.size();i++){ clientSocketVector[i]->write(Message.toStdString().c_str()); } }
if I write like this , I'm getting warning :: QSocketNotifier cannot be enabled or disabled from other thread.
-
Yeah, you have a race condition. You need to emit a signal, instead of calling
write
on all other sockets, and connect that signal to appropriate slots for the objects interested in that data (i.e. the other sockets). That way Qt will handle the thread synchronization for you. -
@kshegunov thanks very much for responding
void Worker::readData(){ QTcpSocket *sock=(QTcpSocket*)sender(); QByteArray Message= sock->readAll(); qDebug()<<"Message "<<Message; for(int i=0;i<clientSocketVector.size();i++){ clientSocket[i]->bytesWritten(64);//Emitted this signal } } void Worker::sendData(qint64){ for(int i=0;i<clientSocket.size();i++){ clientSocket[i]->write(Message.toStdString().c_str()); } } //In server class void server::incomingConnection(qintptr sd) { QMetaObject::invokeMethod(worker, [worker, sd] () -> void { QTcpSocket * socket = new QTcpSocket(worker); connect(socket,SIGNAL(bytesWritten(qint64)),worker,SLOT(sendData(qint64))); if(socket->setSocketDescriptor(sd)){ qDebug()<<"client connected"<<sd; } }
I tried to replace the signal BytesWritten(); by my own making signal but the warning keeps on popping.
-
The slot that is called has to be for an object that's in the same thread for the socket. You need to read on signal-slots and how they're called in multithreaded environment. Just adding a slot anywhere and doing the writing from there won't do.
Ask yourself, when
sendData
is called, which is the thread of th worker object (instance of theWorker
class) and is it the same as for all the objects in theclientSocket
array. Surely not, otherwise you wouldn't still get the message, so you must change the design of your program. -
@kshegunov Thanks very much
You @kshegunov , are a great source of learning, As you suggested about using signals and slots with moveTothread() , I have managed to complete that part and the warning has finally disappeared.
So thanks again @kshegunov , May be we could get a drink , cheers. -
@MokJ said in what is the significance of qintptr socket() in QSocketNotifier class?:
You @kshegunov , are a great source of learning
I should hope so, for my students' sake.
May be we could get a drink , cheers.
Sure, when you're visiting eastern Europe you can poke at me.