Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [SOLVED]Nonblocking/blocking singlethreaded QTcpserver with multiple simultaneous QTcpSockets
Forum Updated to NodeBB v4.3 + New Features

[SOLVED]Nonblocking/blocking singlethreaded QTcpserver with multiple simultaneous QTcpSockets

Scheduled Pinned Locked Moved General and Desktop
7 Posts 3 Posters 5.0k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    alan.martinovic
    wrote on last edited by
    #1

    I have to implement a server which can maintain multiple tcpsockets open and receive messages from them. The tcpsockets should all run in the same thread.

    Here is the current implementation:

    @//server.h
    class MyServer : public QTcpServer

    //server.cpp
    void MyServer::on_newConnection(){
    QTcpSocket *clientConnection = nextPendingConnection();
    if (clientConnection->waitForReadyRead()){
    //DO STUFF WITH RECEIVED MESSAGE
    }@

    This implementation uses the blocking "waitForReadyRead()":http://qt-project.org/doc/qt-5.0/qtnetwork/qabstractsocket.html#waitForReadyRead with the default value. Meaning it waits for 30 seconds for the message to become available.

    But the wiki "Threads, Events and QObjects":http://qt-project.org/wiki/Threads_Events_QObjects states:

    bq. Networking: all low-level Qt networking classes (QTcpSocket, QUdpSocket, QTcpServer, etc.) are asynchronous by design. When you call read(), they just return already available data; when you call write(), they schedule the writing for later. It’s only when you return to the event loop the actual reading/writing takes place. Notice that they do offer synchronous methods (the waitFor* family of methods), but their use is discouraged because they block the event loop while waiting. High-level classes, like QNetworkAccessManager, simply do not offer any synchronous API and require an event loop.

    Please help me to understand the following:

    • What happens in the current implementation in the following situation. Client1 is connected to the Server. The Server is blocked in waitForReadyRead() waiting for Client1 to send the message. At that same time Client 2 tries to establish a connection with the Server.
      Is the socket identifier for Client2 placed on some queue and will be returned next time the Server calls nextPendingConnection() even dough the server is currently blocked with waitForReadyRead() ?

    • How to implement this without the blocking call?

    1 Reply Last reply
    0
    • K Offline
      K Offline
      KA51O
      wrote on last edited by
      #2

      just connect a slot to the "readyRead()":http://qt-project.org/doc/qt-4.8/qiodevice.html#readyRead signal.
      If possible always try to avoid blocking calls in an event-driven framework.

      1 Reply Last reply
      0
      • T Offline
        T Offline
        tomma
        wrote on last edited by
        #3

        QTcpSocket is QIODevice which has readyRead() signal to inform there is data waiting.

        So connect that signal to slot etc where you handle it.

        For example with Qt5 and C++11:

        @
        void MyServer::on_newConnection(){
        QTcpSocket *clientConnection = nextPendingConnection();
        QObject::connect(clientConnection, &QTcpSocket::readyRead, clientConnection{
        QByteArray data = clientConnection->readAll();
        // handle data
        }
        @

        1 Reply Last reply
        0
        • A Offline
          A Offline
          alan.martinovic
          wrote on last edited by
          #4

          Thank you for your answers.
          It didn't occur to me to define the SLOT implementation in the connect. :)

          1 Reply Last reply
          0
          • A Offline
            A Offline
            alan.martinovic
            wrote on last edited by
            #5

            Something came up when i did the change.

            The // handle data part needs a way to modify the server. And that isn't working with the event loop approach.

            Here is a conceptual pseudo code which works in the case with the blocking call.

            @ //server.h
            class MyServer : public QTcpServer
            QList<Client> listOfClients;

            //server.cpp
            void MyServer::on_newConnection(){
                QTcpSocket *clientConnection = nextPendingConnection();
                if (clientConnection->waitForReadyRead()){
                    // Populate the list of clients based on received data
                    listOfClients.append(received_data)
            }@
            

            In the non blocking i have to somehow pass the pointer to the MyServer object. Is there a clean way of doing this?

            1 Reply Last reply
            0
            • A Offline
              A Offline
              alan.martinovic
              wrote on last edited by
              #6

              Figured it out.

              The solution is knowing "what a lambda function is":http://www.cprogramming.com/c++11/c++11-lambda-closures.html and how to pass the local scope to them.

              However, it seems the new syntax for "connect":http://qt-project.org/wiki/New_Signal_Slot_Syntax isn't being recognized.

              @QObject::connect(clientConnection, &QTcpSocket::readyRead, &{
              QByteArray data = clientConnection->readAll();
              //DO STUFF
              });@

              Results in a

              bq. error: no matching function for call to 'MyServer::connect(QTcpSocket*&, void (QIODevice::*)(), MyServer::on_newConnection()::<lambda()>)'

              I bit stuck now. I'm using the Qt 5.1.1 with GCC 4.6.1. will give it a try on other compilers to see if that's the cause.

              1 Reply Last reply
              0
              • A Offline
                A Offline
                alan.martinovic
                wrote on last edited by
                #7

                The problem is with the compiler. It runs fine with Qt 5.1.1 (MSVC 2010, 32 bit). That's a different issue. SOLVED

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved