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. Multithread HTTP server
Forum Updated to NodeBB v4.3 + New Features

Multithread HTTP server

Scheduled Pinned Locked Moved General and Desktop
httpserverthreadpool
7 Posts 4 Posters 4.5k Views 2 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.
  • X Offline
    X Offline
    xalisonx
    wrote on last edited by xalisonx
    #1

    Ey all guys,
    I've tried this piece of code:
    http://doc.qt.digia.com/solutions/4/qtservice/qtservice-example-server.html

    On my server implementation, each http request read and write data from usb. With this code, two simultaneous request interferes with usb communication. I've try to use QMutex, but doesn't works: still locked on the first pass.

    Any ideas?
    Thanks!
    :-)

    1 Reply Last reply
    0
    • A Offline
      A Offline
      andreyc
      wrote on last edited by
      #2

      I would suggest to use a queue for the requests.
      A single thread reads all requests from the queue, reads, writes data from an usb.

      To help you with the current implementation we need to see the code.
      Coould you post it here.

      1 Reply Last reply
      0
      • X Offline
        X Offline
        xalisonx
        wrote on last edited by SGaist
        #3
        #ifndef HTTPSERVER_H
        #define HTTPSERVER_H
        #include <qtcpserver.h>
        #include <QTcpSocket.h>
        #include <qdatetime.h>
        #include <QHostAddress.h>
        #include <QUrlQuery>
        #include <QWidget>
        #include <QRunnable>
        #include <QThreadPool>
        
        class HttpServer : public QTcpServer
        {
            Q_OBJECT
        public:
            HttpServer(quint16 port, QObject* parent, QWidget* w)
                : QTcpServer(parent), disabled(false)
            {
                this->widget = w;
                this->d.Init();
                qDebug()<< "Device Init() OK";
                if (!listen(QHostAddress::Any, port)) {
                    qDebug()<<"FATAL Failed to bind " + this->serverAddress().toString() + ":" + QString::number(this->serverPort());
                } else {
                    qDebug()<<"Server OK "+ this->serverAddress().toString() + ":" + QString::number(this->serverPort());
                }
            }
        
            void incomingConnection(qintptr socket)
            {
                if (disabled)
                    return;
        
                //HttpServerTask *hello = new HttpServerTask(socket);
                //QThreadPool::globalInstance()->start(hello);
        
                // When a new client connects, the server constructs a QTcpSocket and all
                // communication with the client is done over this QTcpSocket. QTcpSocket
                // works asynchronously, this means that all the communication is done
                // in the two slots readClient() and discardClient().
                QTcpSocket* s = new QTcpSocket(this);
                connect(s, SIGNAL(readyRead()), this, SLOT(readClient()));
                connect(s, SIGNAL(disconnected()), this, SLOT(discardClient()));
                s->setSocketDescriptor(socket);
        
                qDebug() <<"Socket " + QString::number(socket) + " new connection";
            }
        
            void pause()
            {
                disabled = true;
            }
        
            void resume()
            {
                disabled = false;
            }
        
        private slots:
            void readClient()
            {
                if (disabled)
                    return;
        
                // This slot is called when the client sent data to the server. The
                // server looks if it was a get request and sends a very simple HTML
                // document back.
                try {
                    QTcpSocket* socket = (QTcpSocket*)sender();
                    qDebug() <<"Socket " + QString::number(socket->socketDescriptor()) + " read";
                    QByteArray buffer = socket->readAll();
                    this->readData = this->readData.append(buffer);
                    if ( this->readData.endsWith( "\r\n" ) ) {
                        QStringList tokens = QString( this->readData ).split(" ");
                        QStringList fulluri = tokens[1].split("?");
                        QString query = "";
                        QString uri = tokens[1];
                        if (fulluri.count() > 1) {
                            uri = fulluri[0];
                            query = fulluri[1];
                        }
        
                        qDebug() <<this->serverAddress().toString() + ":" + QString::number(this->serverPort()) + " " + tokens[0] + " " + tokens[1];
                        if (tokens[0] == "GET") {
                            GetMethod(socket, uri, query);
                            closeSocket(socket);
                            this->readData.clear();
                        } else if(tokens[0] == "POST") {
                            int index = this->readData.indexOf( "\r\n\r\n" );
                            if ( ( 0 < index ) && ( index + 4 < this->readData.length() ) ) {
                                QString data = QString( this->readData.mid( index + 4, this->readData.length() - index - 6 ) );
                                qDebug() <<data;
                                PostMethod(socket, uri, query, data);
                                closeSocket(socket);
                                this->readData.clear();
                            }
        
                        }
                    }
                } catch(std::exception ex) {
                    qCritical() << "FATAL HTTP readClient() EXCEPTION, WHAT="<< qPrintable(ex.what());
                    this->readData.clear();
                } catch (...) {
                    qCritical() << "FATAL HTTP readClient() EXCEPTION";
                    this->readData.clear();
                }
            }
            void discardClient()
            {
                QTcpSocket* socket = (QTcpSocket*)sender();
                socket->deleteLater();
        
                qDebug() <<"Connection closed";
                if (requireExit) {
                    exit(0);
                }
            }
        protected:
            void PostMethod(QTcpSocket* socket, QString uri, QString query, QString data);
            void GetMethod(QTcpSocket* socket, QString uri, QString query);
        
        
        private:
            QByteArray readData;
            bool disabled;
            bool requireExit = false;
            //QMutex mutex;
            QWidget* widget;
        
            QString currentSelectedFolder;
        
        
            void writeOut(QTcpSocket* socket, QString content_type, QString result) {
                QTextStream os(socket);
                os.setAutoDetectUnicode(true);
                os << "HTTP/1.0 200 Ok\r\n"
                      "Content-Type: "+ content_type +"; charset=\"utf-8\"\r\n"
                                                      "\r\n" + result;
                socket->flush();
            }
            void closeSocket(QTcpSocket* socket) {
                socket->close();
                //qDebug() <<"Socket " + QString::number(socket->socketDescriptor()) + " connection closed";
                if (socket->state() == QTcpSocket::UnconnectedState) {
                    delete socket;
                }
            }
        };
        
        
        #endif // HTTPSERVER_H
        

        [edit: Added missing coding tags SGaist]

        1 Reply Last reply
        0
        • X Offline
          X Offline
          xalisonx
          wrote on last edited by SGaist
          #4

          This is the .cpp file:

          void HttpServer::GetMethod(QTcpSocket* socket, QString uri, QString query) {
              QString content_type = "text/plain";
              QString result = "";
              if (uri == "/command1") {
                  //QMutexLocker locker(&this->mutex);
                  // READ & WRITE USB SYNCRONOUSLY
                  // this MUTEX doesn't works!!!! :(
                  //locker.unlock();
              } else if (uri == "/command2") {
                   // READ & WRITE USB SYNCRONOUSLY
              } else if (uri == "/ping") {
                  result = "pong";
          
              } else if (uri == "/quit") {
                  //QMutexLocker locker(&this->mutex);
                  this->close();
                  d.Close();
                  //locker.unlock();
                  requireExit = true;
                  result = "done";
              } else if ( uri.endsWith( ".html" )   ||
                          uri.endsWith( ".htm"  )   ||
                          uri.endsWith( ".txt"  )   ||
                          uri.endsWith( ".xml"  ) ) {
                  QString filename = QApplication::applicationDirPath() + "/doc_root" + uri;
                  if ( QFile::exists( filename ) ) {
                      QFile file( filename );
                      if ( file.open( QFile::ReadOnly | QFile::Text ) ) {
                          QTextStream in( &file );
                          result = in.readAll();
                          file.close();
                      }
                  }
              }
          
              writeOut(socket, content_type, result);
              qDebug() <<"Response: "<< result;
          }
          
          
          void HttpServer::PostMethod(QTcpSocket* socket, QString uri, QString query, QString data) {
              QString content_type = "text/plain";
              QString result = "";
              if (uri == "/largedatacommand") {
                  //QMutexLocker locker(&this->mutex);
                  // READ & WRITE USB SYNCRONOUSLY
                  // this MUTEX doesn't works!!!! :(
                  //locker.unlock();
              } 
              writeOut(socket, content_type, result);
              qDebug() <<"Response: "<< result;
          }
          

          That's all.
          PS: how to formatting code in this new forum?? ;) thanks!

          [edit: added missing coding tags SGaist]

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            Hi,

            The code formatting is: three ` (back sticks), start the code on a new line and again three to close the block

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            0
            • X Offline
              X Offline
              xalisonx
              wrote on last edited by
              #6

              Thanks SGaist!

              I've found this example: http://doc.qt.io/qt-5/qtnetwork-threadedfortuneserver-example.html

              May be the right way!

              1 Reply Last reply
              0
              • S Offline
                S Offline
                s.frings74
                wrote on last edited by
                #7

                Maybe my HTTP server library helps you: http://stefanfrings.de/qtwebapp/index-en.html
                It's multi-threaded.

                1 Reply Last reply
                1

                • Login

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