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. QWebSocketServer and QThread
Forum Updated to NodeBB v4.3 + New Features

QWebSocketServer and QThread

Scheduled Pinned Locked Moved Solved General and Desktop
3 Posts 2 Posters 386 Views
  • 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.
  • R Offline
    R Offline
    red_spider
    wrote on last edited by
    #1

    Hello everyone. for some reasons, namely when a user fills a stream, others do not have access to the server,
    I need to make separate threads on QWebSocket, so I know that QWebSocket cannot be passed to other threads, so I wrote an example in which QTcpServer -> socketDescriptor - > QThread -> QTcpSocket -> QWebSocketServer::handleConnection and accordingly via newConnection I get a QWebSocket,
    the connection is established and the data is received by the server and can be processed, but when I try to send back to the client nothing happens except one error in the console,

    QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
    

    here is a simple example server, tested from the standard echoclient example
    if you do not transfer the work of QWebSocketServer to a heavy thread, then everything works.
    maybe someone has some idea what the problem is, or has faced such before.

    Thank you for attention.

    example
    main.cpp

    #include <QCoreApplication>
    #include "TcpServerMultithreading.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        TcpServerMultithreading serverTcp(1551);
        return a.exec();
    }
    

    TcpServerMultithreading.h

    #ifndef TCPSERVERMULTITHREADING_H
    #define TCPSERVERMULTITHREADING_H
    
    #include <QObject>
    #include <QTcpServer>
    
    #include <QTcpSocket>
    #include <QtWebSockets/QWebSocketServer>
    #include <QtWebSockets/QWebSocket>
    
    class TcpServerMultithreading : public QTcpServer
    {
        Q_OBJECT
    public:
        explicit TcpServerMultithreading(quint16 port, QObject *parent = nullptr);
    
    protected:
        void incomingConnection(qintptr socketDescriptor) override;
    
    
    public slots:
        void parseMessage(const QString &message);
        void onNewConnection();
    
    private:
        int socketDescriptor;
        QWebSocketServer *m_pWebSocketServer;
    };
    
    #endif // TCPSERVERMULTITHREADING_H
    

    TcpServerMultithreading.cpp

    #include "TcpServerMultithreading.h"
    #include "UserConnectThread.h"
    
    TcpServerMultithreading::TcpServerMultithreading(quint16 port, QObject *parent)
        : QTcpServer{parent}
    {
        if (listen(QHostAddress::Any, port))
        {
            qDebug() << "SSL Echo Server listening on port" << serverPort();
        }
        else
        {
            qDebug() << "ERROR: " << errorString();
        }
    }
    
    void TcpServerMultithreading::incomingConnection(qintptr socketDescriptor)
    {
        qDebug() << Q_FUNC_INFO << socketDescriptor;
    
        UserConnectThread *userConnectThread = new UserConnectThread(socketDescriptor, this);
    
    
        userConnectThread->start();
    }
    
    
    void TcpServerMultithreading::parseMessage(const QString &message)
    {
        qDebug() << Q_FUNC_INFO << message;
    
        QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
    
        pClient->sendTextMessage(QString("return: %1").arg(message));
    }
    
    void TcpServerMultithreading::onNewConnection()
    {
        qDebug() << Q_FUNC_INFO;
        QWebSocket *m_pSocket = m_pWebSocketServer->nextPendingConnection();
    
        connect(m_pSocket, &QWebSocket::textMessageReceived, this, &TcpServerMultithreading::parseMessage);
    }
    

    UserConnectThread.h

    #ifndef USERCONNECTTHREAD_H
    #define USERCONNECTTHREAD_H
    
    #include <QObject>
    #include <QThread>
    #include <QTcpSocket>
    #include <QtWebSockets/QWebSocketServer>
    #include <QtWebSockets/QWebSocket>
    
    class UserConnectThread : public QThread
    {
        Q_OBJECT
    public:
        explicit UserConnectThread(int socketDescriptor, QObject *parent = nullptr);
    
        void run() override;
    signals:
        void sendToClient(QString message);
    
    public slots:
        void parseMessage(const QString &message);
        void onNewConnection();
    
    private:
        int socketDescriptor;
        QWebSocketServer *m_pWebSocketServer;
    };
    
    #endif // USERCONNECTTHREAD_H
    

    UserConnectThread.cpp

    #include "UserConnectThread.h"
    
    UserConnectThread::UserConnectThread(int socketDescriptor, QObject *parent)
        : QThread{parent}, socketDescriptor(socketDescriptor)
    {
    
    }
    
    void UserConnectThread::run()
    {
        qDebug() << "Run Thread";
        QTcpSocket *tcpSocket = new QTcpSocket();
    
    
        if (!tcpSocket->setSocketDescriptor(socketDescriptor)) {
            //emit error(tcpSocket->error());
            return;
        }
    
        m_pWebSocketServer = new QWebSocketServer(QStringLiteral("SSL Echo Server"),
                                                  QWebSocketServer::NonSecureMode);
    
    
        connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
                this, &UserConnectThread::onNewConnection);
    
    
        m_pWebSocketServer->handleConnection(tcpSocket);
    
        exec();
    }
    
    void UserConnectThread::parseMessage(const QString &message)
    {
        qDebug() << Q_FUNC_INFO << message;
    
        QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
    
        int sizeSend = pClient->sendTextMessage(QString("return: %1").arg(message));
        qDebug() << Q_FUNC_INFO << "send: " << sizeSend;
    }
    
    void UserConnectThread::onNewConnection()
    {
        qDebug() << Q_FUNC_INFO;
        QWebSocket *m_pSocket = m_pWebSocketServer->nextPendingConnection();
    
        connect(m_pSocket, &QWebSocket::textMessageReceived, this, &UserConnectThread::parseMessage);
        connect(this, &UserConnectThread::sendToClient, m_pSocket, &QWebSocket::sendTextMessage);
    }
    
    Christian EhrlicherC 1 Reply Last reply
    0
    • R red_spider

      Hello everyone. for some reasons, namely when a user fills a stream, others do not have access to the server,
      I need to make separate threads on QWebSocket, so I know that QWebSocket cannot be passed to other threads, so I wrote an example in which QTcpServer -> socketDescriptor - > QThread -> QTcpSocket -> QWebSocketServer::handleConnection and accordingly via newConnection I get a QWebSocket,
      the connection is established and the data is received by the server and can be processed, but when I try to send back to the client nothing happens except one error in the console,

      QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
      

      here is a simple example server, tested from the standard echoclient example
      if you do not transfer the work of QWebSocketServer to a heavy thread, then everything works.
      maybe someone has some idea what the problem is, or has faced such before.

      Thank you for attention.

      example
      main.cpp

      #include <QCoreApplication>
      #include "TcpServerMultithreading.h"
      
      int main(int argc, char *argv[])
      {
          QCoreApplication a(argc, argv);
          TcpServerMultithreading serverTcp(1551);
          return a.exec();
      }
      

      TcpServerMultithreading.h

      #ifndef TCPSERVERMULTITHREADING_H
      #define TCPSERVERMULTITHREADING_H
      
      #include <QObject>
      #include <QTcpServer>
      
      #include <QTcpSocket>
      #include <QtWebSockets/QWebSocketServer>
      #include <QtWebSockets/QWebSocket>
      
      class TcpServerMultithreading : public QTcpServer
      {
          Q_OBJECT
      public:
          explicit TcpServerMultithreading(quint16 port, QObject *parent = nullptr);
      
      protected:
          void incomingConnection(qintptr socketDescriptor) override;
      
      
      public slots:
          void parseMessage(const QString &message);
          void onNewConnection();
      
      private:
          int socketDescriptor;
          QWebSocketServer *m_pWebSocketServer;
      };
      
      #endif // TCPSERVERMULTITHREADING_H
      

      TcpServerMultithreading.cpp

      #include "TcpServerMultithreading.h"
      #include "UserConnectThread.h"
      
      TcpServerMultithreading::TcpServerMultithreading(quint16 port, QObject *parent)
          : QTcpServer{parent}
      {
          if (listen(QHostAddress::Any, port))
          {
              qDebug() << "SSL Echo Server listening on port" << serverPort();
          }
          else
          {
              qDebug() << "ERROR: " << errorString();
          }
      }
      
      void TcpServerMultithreading::incomingConnection(qintptr socketDescriptor)
      {
          qDebug() << Q_FUNC_INFO << socketDescriptor;
      
          UserConnectThread *userConnectThread = new UserConnectThread(socketDescriptor, this);
      
      
          userConnectThread->start();
      }
      
      
      void TcpServerMultithreading::parseMessage(const QString &message)
      {
          qDebug() << Q_FUNC_INFO << message;
      
          QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
      
          pClient->sendTextMessage(QString("return: %1").arg(message));
      }
      
      void TcpServerMultithreading::onNewConnection()
      {
          qDebug() << Q_FUNC_INFO;
          QWebSocket *m_pSocket = m_pWebSocketServer->nextPendingConnection();
      
          connect(m_pSocket, &QWebSocket::textMessageReceived, this, &TcpServerMultithreading::parseMessage);
      }
      

      UserConnectThread.h

      #ifndef USERCONNECTTHREAD_H
      #define USERCONNECTTHREAD_H
      
      #include <QObject>
      #include <QThread>
      #include <QTcpSocket>
      #include <QtWebSockets/QWebSocketServer>
      #include <QtWebSockets/QWebSocket>
      
      class UserConnectThread : public QThread
      {
          Q_OBJECT
      public:
          explicit UserConnectThread(int socketDescriptor, QObject *parent = nullptr);
      
          void run() override;
      signals:
          void sendToClient(QString message);
      
      public slots:
          void parseMessage(const QString &message);
          void onNewConnection();
      
      private:
          int socketDescriptor;
          QWebSocketServer *m_pWebSocketServer;
      };
      
      #endif // USERCONNECTTHREAD_H
      

      UserConnectThread.cpp

      #include "UserConnectThread.h"
      
      UserConnectThread::UserConnectThread(int socketDescriptor, QObject *parent)
          : QThread{parent}, socketDescriptor(socketDescriptor)
      {
      
      }
      
      void UserConnectThread::run()
      {
          qDebug() << "Run Thread";
          QTcpSocket *tcpSocket = new QTcpSocket();
      
      
          if (!tcpSocket->setSocketDescriptor(socketDescriptor)) {
              //emit error(tcpSocket->error());
              return;
          }
      
          m_pWebSocketServer = new QWebSocketServer(QStringLiteral("SSL Echo Server"),
                                                    QWebSocketServer::NonSecureMode);
      
      
          connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
                  this, &UserConnectThread::onNewConnection);
      
      
          m_pWebSocketServer->handleConnection(tcpSocket);
      
          exec();
      }
      
      void UserConnectThread::parseMessage(const QString &message)
      {
          qDebug() << Q_FUNC_INFO << message;
      
          QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
      
          int sizeSend = pClient->sendTextMessage(QString("return: %1").arg(message));
          qDebug() << Q_FUNC_INFO << "send: " << sizeSend;
      }
      
      void UserConnectThread::onNewConnection()
      {
          qDebug() << Q_FUNC_INFO;
          QWebSocket *m_pSocket = m_pWebSocketServer->nextPendingConnection();
      
          connect(m_pSocket, &QWebSocket::textMessageReceived, this, &UserConnectThread::parseMessage);
          connect(this, &UserConnectThread::sendToClient, m_pSocket, &QWebSocket::sendTextMessage);
      }
      
      Christian EhrlicherC Online
      Christian EhrlicherC Online
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by Christian Ehrlicher
      #2

      @red_spider said in QWebSocketServer and QThread:

      connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
      this, &UserConnectThread::onNewConnection);

      Common error - since this is living in the main thread, the slot is executed there.
      Ise the worker approach instead. But don't see why a thread is needed here at all though.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      R 1 Reply Last reply
      2
      • Christian EhrlicherC Christian Ehrlicher

        @red_spider said in QWebSocketServer and QThread:

        connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
        this, &UserConnectThread::onNewConnection);

        Common error - since this is living in the main thread, the slot is executed there.
        Ise the worker approach instead. But don't see why a thread is needed here at all though.

        R Offline
        R Offline
        red_spider
        wrote on last edited by
        #3

        @Christian-Ehrlicher thank you for your reply, it will solve my problem there.

        distribution into separate streams, it is necessary because when you download a large stream of binary data through a socket, everyone else who has their own sockets does not receive a response, they wait until the data is loaded

        1 Reply Last reply
        0
        • R red_spider has marked this topic as solved on

        • Login

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