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

QTcpServer for manage many clients with blocking operations



  • Hi all

    I'm developing a server tool for manage many clients connected through socket connections. For the server I use QTcpServer and for the clients (developed by me also) QTcpSocketas as obvious. Server need to continuously interact with clients with also some blocking commands waiting for immediately reply than I need to use threads for keep GUI responsive. Using the returned client socket after connection in a separate thread is cleared explained in the documentation by derive incomingConnection() and use the socketdescriptor value. Now the problem. Assign to each client a dedicated thread doesn't seem a good idea cause connected clients can be many. Alternative can be use a thread pool for execute each single task. There are good examples regarding how to use socket in a thread in the Qt documentation and also around in Internet but all example I found, after passed the socketDescriptor to the thread for allow to use the QTcpSocket, close the socket once the operation is finished that is not what I want to do. I need the socket connection will remain open for all the time but in this case how to "move" temporarily the socket to the thread just only for execute the blocking operation?
    Thank you for the help



  • @FalsinSoft said in QTcpServer for manage many clients with blocking operations:

    I need the socket connection will remain open for all the time but in this case how to "move" temporarily the socket to the thread just only for execute the blocking operation?

    I would suggest you to use QtConcurrent::run() to run the function in another thread and wait of execution done with help of QEventLoop and QFutureWatcher.

    Something like:

    // suppose return function type is void
    QFutureWatcher<void> watcher;
    QEventLoop loop;
    
    connect(&watcher, &QFutureWatcher<void>::finished, &loop, &QEventLoop::quit);
    connect(&watcher, &QFutureWatcher<void>::canceled, &loop, &QEventLoop::quit);
    QFuture<void> future= QtConcurrent::run(this, &MyClass::longFunctionToRun, parameters);
    watcher.setFuture(future);
    // wait until future is done without locking current thread!!
    qDebug() << "Waiting result";
    loop.exec();
    qDebug() << "Processing done.";
    
    


  • QtConcurrent::run() basically use a thread pool but the problem remain. Based to the documentation QTcpSocket can not be used to a thread different from the original one where it has been created. I can pas the socketDescriptor and create the QTcpSocket inside the function ran with QtConcurrent::run() but when function will finish the QTcpSocket will be destroyed and the socket closed....


  • Lifetime Qt Champion

    @FalsinSoft
    Hi
    Do you really need to use the blocking api ?
    Using the async API only takes a little bit more code to have a state system to do the next thing after getting a reply.



  • Do you really need to use the blocking api ?

    Yes, there are just a couple of commands but manage them with asynchronous code excessively complicates the whole project



  • @FalsinSoft said in QTcpServer for manage many clients with blocking operations:

    QtConcurrent::run() basically use a thread pool but the problem remain. Based to the documentation QTcpSocket can not be used to a thread different from the original one where it has been created.

    My suggestion was to "export" the long time processing function into another thread, but this does not mean socket read/write.
    When processing is done, you can then send result to TCP client from the right thread.

    But I don't have any idea of your software, maybe this is not applicable.

    Another possibility is to define a QThreadPool depending on the cpu count, and loop through this pool to select a thread to handle new connected client.
    So you would not look main thread. But, as you should know, Qt design is asynchronous, so use it with blocking API is not the best way.

    I would suggest you to rework your application concept to be more "Qt friendly" or perhaps use another C++ library which better fit your needs.



  • I know asynchronous is the better way use Qt but, in my opinion, sometimes is useless to complicate too much the code when a more simply solution of use a blocking operation is available. I'm referring to the Qt function QAbstractSocket::waitForReadyRead() that is available exactly for this purpose (there is also the official example "Blocking Fortune Client Example"). In this thread I just would to know if is possible to use this blocking feature in the way I need. If not possible I'll move to the asynchronous way...


Log in to reply