Home

A simple HTTP Server

The service in this example is based on the HTTP daemon example of Qt.

It is a very simple implementation of a HTTP daemon that listens on port 8080 and sends back a simple HTML page back for every GET request it gets. After sending the page, it closes the connection.

    // HttpDaemon is the the class that implements the simple HTTP server.
    class HttpDaemon : public QServerSocket
    {
        Q_OBJECT
    public:
        HttpDaemon( QObject* parent=0 ) :
            QServerSocket(8080,1,parent), disabled(FALSE)
        {
            if ( !ok() ) {
                qService->reportEvent( "Failed to bind to port 8080", QtService::Error );
                exit( 1 );
            }
        }

        void newConnection( int socket )
        {
            if ( disabled )
                return;

            // When a new client connects, the server constructs a QSocket and all
            // communication with the client is done over this QSocket. QSocket
            // works asynchronouslyl, this means that all the communication is done
            // in the two slots readClient() and discardClient().
            QSocket* s = new QSocket( this );
            connect( s, SIGNAL(readyRead()), this, SLOT(readClient()) );
            connect( s, SIGNAL(delayedCloseFinished()), this, SLOT(discardClient()) );
            s->setSocket( socket );

            qService->reportEvent( "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.
            QSocket* socket = (QSocket*)sender();
            if ( socket->canReadLine() ) {
                QStringList tokens = QStringList::split( QRegExp("[ \r\n][ \r\n]*"), socket->readLine() );
                if ( tokens[0] == "GET" ) {
                    QTextStream os( socket );
                    os.setEncoding( QTextStream::UnicodeUTF8 );
                    os << "HTTP/1.0 200 Ok\r\n"
                        "Content-Type: text/html; charset=\"utf-8\"\r\n"
                        "\r\n"
                        "<h1>Nothing to see here</h1>\n";
                    socket->close();

                    qService->reportEvent( "Wrote to client" );
                }
            }
        }
        void discardClient()
        {
            QSocket* socket = (QSocket*)sender();
            delete socket;

            qService->reportEvent( "Connection closed" );
        }

    private:
        bool disabled;
    };
The server implementation is almost identical to the standard example. Instead of using qWarning to print messages to the console it uses the QtService::reportEvent() function to send messages and status reports to the system event log. The server in this case also supports a paused state in which case incoming requests are ignored.

The HttpService class subclasses QtService to implement the service functionality.

    class HttpService : public QtService
    {
    public:
        HttpService()
            : QtService( "Qt HTTP Daemon", "A dummy HTTP service implemented with Qt" )
        {}
The constructor calls the QtService constructor. The first two parameters are the name of the service, "Qt HTTP Daemon", and a description.

    protected:
        int run( int argc, char **argv )
        {
            QApplication app( argc, argv, FALSE );

            daemon = new HttpDaemon( &app );
            return app.exec();
        }
The implementation of run() creates a QApplication object (passing FALSE as the third parameter, as this application doesn't provide a user interface) and creates an instance of the HTTP server using operator new, passing the application object as the parent to ensure that the object gets destroyed. (1) Control is then passed to the event loop.

        void pause()
        {
            daemon->pause();
        }

        void resume()
        {
            daemon->resume();
        }
    private:
        HttpDaemon *daemon;
    };
The implementations of pause() and resume() forward the request to the server object.

    #include "main.moc"

    int main( int argc, char **argv )
    {
        HttpService service;
        return service.parseArguments( argc, argv );
    }
The main entry point function creates the service object and uses the parseArguments() function to handle the command line parameters passed to the application (see the QtService::parseArguments() documentation for details).
  1. A QApplication object has to exist before the server can be created, so we cannot use a HttpDaemon object as a member of the service class. Back...

Copyright © 2003-2005 TrolltechTrademarks
Qt Solutions