Home > Software design >  How to send data to a specific client on a multithreaded server
How to send data to a specific client on a multithreaded server

Time:09-26

I am trying to build a multithreaded server. The problem that I am encountering is that the emitted signal sends message to all clients instead to the specific one on a specific thread.

I tried to solve the issue by creating a QList of threads, but how do I connect them specifically?? When signal is emitted, it wakes up all my threads, the problem is getting worse by each connection, since the clients are dynamically allocated as they are connecting.

Code:

void NetworkServer::incomingConnection(qintptr socketDescriptor)
{
    QThread *thread = new QThread;
    threadhandle *session = new threadhandle;

    QObject::connect(this,    &NetworkServer::stopped,  session, &threadhandle::close);
    QObject::connect(this,    &NetworkServer::stopped,  thread,  &threadhandle::quit);
    QObject::connect(session, &threadhandle::closed,    thread,  &threadhandle::quit);

    QObject::connect(thread, &QThread::started, this, &NetworkServer::threadStarted, Qt::DirectConnection);
    QObject::connect(thread, &QThread::finished, this, &NetworkServer::threadFinished, Qt::DirectConnection);

    QObject::connect(thread, &QThread::finished, session, &QObject::deleteLater);
    QObject::connect(thread, &QThread::finished, thread, &QObject::deleteLater);
    
//the problem is here, I can send message to all clients connected, but how to specifiy a thread/client???
    QObject::connect(this, &NetworkServer::sendMsgToThread, session, &threadhandle::sendMsgToClient);

    thread->start();

    session->moveToThread(thread);

    QMetaObject::invokeMethod(session, "open", Qt::QueuedConnection, Q_ARG(qintptr, socketDescriptor));

Update - 40 minutes later - Problem solved

I apologize for not providing more details, basically I am building a simple client-server relationship. Message is send from server GUI line in text format to a specific client.

After some thinking I came up with a solution. so for each new thread, we will append its session to: QList<threadhandle*>sessionList

After that we are going to edit the sendMsgToClient()

// user clicks on Send Message button in GUI
void NetworkServer::sendMsgToClient(int clientNum, QString msg)
{

//connect the signal to a specific thread, clientNum is selected from a table in mainWindow GUI where the NetworkServer class is initiated
QObject::connect(this, &NetworkServer::sendMsgToThread, sessionList.at(clientNum), &threadhandle::sendMsgToClient);
     
//emit the signal to specific thread 
emit sendMsgToThread(clientNum, msg);

//disconnect the signal, since it is no longer needed
QObject::disconnect(this, &NetworkServer::sendMsgToThread, sessionList.at(clientNum), &threadhandle::sendMsgToClient);
}

CodePudding user response:

Hard to say really without MRE that builds and presents your exact problem. But, guessing from context: no clue how NetworkServer::sendMsgToThread or threadhandle::sendMsgToClient are implemented, but I guess you could store the thread ID/index/any other identifier and then pass it to specific thread only, possible via some proxy object?

Point is, sendMsgToThread gets connected to multiple slots, which is probably not what you want; instead those single session-thread pairs need to be somehow distinguished, e.g. by thread ID/its index in list, whatever.

I guess you could wrap the session and thread in some other class, that would be stored (and referred to) by the server by some of the aforementioned IDs, and it would forward the messages to the worker (session) object. But I cannot really tell without at least basic knowledge of your code's architecture.

  • Related