it-swarm-eu.dev

Kann C ++ als serverseitige Webentwicklungssprache verwendet werden?

Ich möchte mit C++ als "Skriptsprache" auf der Serverseite in die Webentwicklung einsteigen. Meine Serverinfrastruktur basiert auf * nix, daher ist die Webentwicklung in C++ unter Azure nicht anwendbar und C++/CLI ASP.NET ist ebenfalls nicht anwendbar.

Kann die Webentwicklung unabhängig von älteren CGI-Anwendungen mit C++ durchgeführt werden?

34
Scott Davies

Absolut.

Es gibt sogar mehrere Frameworks für deren Entwicklung, darunter Wt , cppcms , CSP und andere. Die Hauptimplementierung von FastCGI befindet sich in C und unterstützt direkt mehrere Sprachen , einschließlich C++.

Jede Programmiersprache, die Zeichenfolgen analysieren kann, kann in CGI oder einem Servlet verwendet werden. Jede Sprache, die Bindungen mit C-Bibliotheken implementieren kann, kann auch zum Entwickeln von Modulen für ISAPI- oder Apache-kompatible Server verwendet werden.

In C++ ist das nicht besonders einfach, und es gibt nur wenige gute Template-Engines, aber es kann getan werden.

Die Frage, ob dies eine gute Idee ist, ist natürlich eine ganz andere Sache. :) :)

Beachten Sie: Wichtige Websites wie Amazon.com, eBay und Google verwenden C++ für Teile ihrer Infrastruktur. Beachten Sie jedoch, dass Google C++ nur für geschwindigkeitskritische Systeme verwendet und Amazon.com erst vor relativ kurzer Zeit von LISP abgewichen ist (was einige seiner leitenden Angestellten verärgerte :).

Facebook hat früher PHP zu C++ kompiliert, aber der HipHop-Compiler (teilweise in C++ geschrieben) wurde inzwischen als virtuelle Bytecode-Maschine umgerüstet.

56
greyfade

Warum nicht?

Die Dating-Site OkCupid wird mit C++ erstellt. Es gibt wahrscheinlich andere Beispiele.

Es gibt auch ein Qt-inspiriertes Toolkit für die Entwicklung von Webanwendungen mit C++ namens Wt .

18
Vitor Py

Wenn Sie planen, Ihre Webanwendung in C++ zu schreiben, wäre es eine völlige Verschwendung, sie dann als CGI zu verbinden.

Mein Vorschlag wäre, es asynchron mit ASIO (Asynchrone E/A) zu erstellen. Damit können Sie einen blitzschnellen Webdienst erstellen (kombinieren Sie ihn mit nginx als Reverse-Proxy und Statics-Server, um die besten Effekte zu erzielen). Kombinieren Sie dies mit einer Vorlagenbibliothek wie Wt und Sie können Zehntausende Anfragen pro Sekunde von einem einzelnen Server aus bearbeiten.

Ob dies eine praktische Alternative zum dynamischen Webframework ist, ist ein weiteres Problem.

11
vartec

Die kurze Antwort lautet: ALLES kann zum Schreiben einer Webseite verwendet werden, sofern diese die Eingabe lesen, interpretierbare Ausgaben schreiben und vom Webserver ausführbar ist.

Technisch kann jede Sprache als CGI-Skript verwendet werden, vorausgesetzt:

  1. Interpretiert alle vom Server präsentierten Eingaben und Umgebungen
  2. Ausgaben in einer bekannten Auszeichnungssprache (im Allgemeinen HTML)
  3. Kann vom Server ausgeführt werden

Es gibt auch andere Möglichkeiten. Perl kann als Wrapper um c/c ++ - Code erstellt werden und fungiert als Interpretationsschicht zwischen den beiden (und dies schließt Perl-Module nicht ein, die vollständig als C kompiliert sind).

9
Avatar_Squadron

am Anfang war es ziemlich häufig - die ersten Websites, an denen ich Ende der 90er Jahre arbeitete, waren ISAPI-Erweiterungen, die in C++ geschrieben wurden, und sie funktionierten ziemlich gut.

7
Steven A. Lowe

Es scheint, dass Microsoft glaubt, dass dies auch möglich ist. Check out Casablanca Dies ist eine neue Reihe von Werkzeugen für (wie es scheint) Azure mit C++.

Casablanca ist ein Projekt, mit dem untersucht werden soll, wie C++ - Entwickler am besten unterstützt werden können, die die radikale Veränderung der Softwarearchitektur, die Cloud Computing darstellt, nutzen möchten.

Folgendes erhalten Sie mit Casablanca:

  • Unterstützung für den Zugriff auf REST -Dienste aus nativem Code unter Windows Vista, Windows 7 und Windows 8 Consumer Preview durch Bereitstellung asynchroner C++ - Bindungen für HTTP-, JSON- und URIs
  • Ein Visual Studio-Erweiterungs-SDK, mit dem Sie clientseitigen C++ - HTTP-Code in Ihre Windows 8 Metro-App schreiben können
  • Unterstützung für das Schreiben von nativem Code REST für Azure, einschließlich Visual Studio-Integration
  • Praktische Bibliotheken für den Zugriff auf Azure-Blob- und Warteschlangenspeicher von nativen Clients als erstklassige PaaS-Funktion (Platform-as-a-Service)
  • Ein konsistentes und leistungsstarkes Modell zum Erstellen asynchroner Vorgänge basierend auf C++ 11-Funktionen
  • Eine C++ - Implementierung des auf Erlang-Akteuren basierenden Programmiermodells
  • Eine Reihe von Beispielen und Dokumentationen
5
gbjbaanb

Für PHP können Sie schreiben Sie Ihre eigenen C/C++ - Erweiterungen und erhalten auf diese Weise gute Leistungsvorteile. Wenn ich einen wirklich CPU-intensiven Teil meiner Webanwendung hätte, würde ich wahrscheinlich Erstellen Sie eine kleine C++ - Bibliothek, die diese Verarbeitung in die Erweiterung verlagert und das Ergebnis dann an PHP] zurückgibt. Anschließend gibt das PHP es an den Browser aus).

Das andere, was die Leute nicht oft in Betracht ziehen, ist das Auslagern bestimmter CPU-Verarbeitungen auf die Clientseite, z. JavaScript/jQuery. Wenn ich einen Webserver habe, benötige ich möglicherweise eine 3-GHz-CPU, um eine CPU-intensive Verarbeitung für eine bestimmte Funktion durchzuführen (möglicherweise eine Datenverarbeitung). Mein Unternehmen zahlt jeden Monat Geld für diesen Server, um ihn am Laufen zu halten. Wenn ich den Betrieb für 100 gleichzeitige Benutzer skalieren möchte, die diese CPU-intensive Aufgabe gleichzeitig ausführen, benötige ich möglicherweise mehrere CPUs und Server, was die Kosten für mein Unternehmen erhöht. Wenn ich diese CPU-intensive Aufgabe auf die Clientseite verlagere, kann jeder Benutzer, der die Website besucht, seine Daten selbst verarbeiten, und ich muss meine Serverkapazität nicht erhöhen, wodurch ich Geld spare.

Immerhin mit der kollektiven Leistung von mehr als 100 Desktops/Tablets/Handys, die die Verarbeitung für Sie erledigen, ist das viel mehr Leistung als Ihr Server, der irgendwo in einem Rechenzentrum sitzt und Ihr Geschäftsgeld jeden Monat kostet, um weiterzulaufen. Möglicherweise würde Ihr Server dann nur Daten aus der Datenbank abrufen, Inhalte bereitstellen und die Daten vor/nach der Verarbeitung und Validierung ein wenig bereitstellen, bevor sie wieder in der Datenbank gespeichert werden. Offensichtlich würden Sie den clientseitigen Code nicht zu CPU-intensiv machen, was die Benutzeroberfläche des Webbrowsers blockieren/einfrieren könnte. Sie könnten eine AJAX - Anfrage an den Server auslösen, die Daten abrufen und dann die verarbeiten Daten asynchron clientseitig, sodass die Benutzeroberfläche des Webbrowsers vollständig nutzbar ist.

2
zuallauz

Ja, es kann verwendet werden. Die anderen haben verschiedene Ansätze erwähnt. Hier ist mein eigener Ansatz. Der Vorteil ist, dass es vollständig portabel und in sich geschlossen ist. Alle ausgewählten Bibliotheken hängen nur von ANSI C ab. Für die Einrichtung sind nur der Linux-Kernel und ein C-Compiler (und die offensichtlichen Dinge wie Busybox, Bash usw.) (oder Windows) erforderlich und ein Compiler), es werden keine zusätzlichen Bibliotheken benötigt, keine ausgefallenen riesigen Installationen.

Das Ergebnis ist ein einzelnes Programm, das sowohl ein Webserver als auch ein dynamischer Seitengenerator ist (ersetzt sowohl "Apache" als auch "PHP") und über SQLite auf die Datenbank zugreifen kann.

Verwendete Bibliotheken:

  • Mungo - HTTP-Server
  • SQLite - SQL-Datenbank
  • MiniXML - Erleichtert die dynamische Seitengenerierung. irgendwie wie Javascript createElement

Der Rest dieser Antwort ist eine vollständige Einrichtungsanleitung für Linux. Sowohl SQlite als auch MiniXML sind optional, die Anleitung behandelt jedoch die vollständige Installation. Es liegt an Ihnen, die nicht benötigten Teile zu kommentieren, wenn Sie SQLite oder MiniXML deaktivieren möchten.

1. Laden Sie die 3 Bibliotheken herunter

2. Bereiten Sie Ihren Ordner vor

  • Erstellen Sie einen leeren Ordner (wir nennen ihn den Hauptordner)
  • Fügen Sie die folgenden Dateien ein:
    • Aus dem sqlite tar.gz: sqlite3.c , sqlite3.h
    • Aus der Mongoose Zip: mongoose.c , mongoose.h
    • Aus dem mxml tar.gz: mxml.h

3. Kompiliere mxml

Möglicherweise haben Sie bemerkt, dass mxml.c fehlt. Dies liegt daran, dass wir eine statische mxml-Bibliothek erstellen müssen. Wechseln Sie in den Ordner, in den die Datei mxml tar.gz heruntergeladen wurde, und führen Sie Folgendes aus:

tar -xvf mxml-<version>.tar.gz #Extract the tar
cd mxml-<version> #Go to the newly extracted directory
./configure #prepare the compiler
make #compile, you may need to install "make" first.

Sobald die Kompilierung abgeschlossen ist, werden viele Dateien generiert. Die einzige Datei, die uns interessiert, ist libmxml.a. Kopieren Sie diese Datei in den Hauptordner.

3.1 Doublecheck

Überprüfen Sie, ob der Hauptordner Folgendes enthält:

  • Für Mungo: mongoose.c, mongoose.h
  • Für mxml: libmxml.a, mxml.h
  • für SQLite: sqlite.c, sqlite.h

4. main.c

Lassen Sie uns das eigentliche Programm erstellen, eine main.c - Datei im Hauptordner erstellen. Hier ist ein Grundgerüst, mit dem Sie beginnen können.

#include <string.h>
#include <stdio.h>

#include "mongoose.h"
#include "mxml.h"
#include "sqlite3.h"

/***Sqlite initialization stuff***/
//comment out everything sqlite related if you don't want sqlite, including the callback function and the include "sqlite3.h"
static int callback(void * custom, int argc, char **argv, char **azColName);
char *zErrMsg = 0;
sqlite3 *db;
int rc;

/***Just some laziness shortcut functions I made***/
typedef mxml_node_t * dom; //type "dom" instead of "mxml_node_t *"
#define c mxmlNewElement   //type "c" instead of "mxmlNewElement"
inline void t(dom parent,const char *string) //etc
{
    mxmlNewText(parent, 0, string);
}

//type "sa" instead of "mxmlElementSetAttr"
inline void sa(dom element,const char * attribute,const char * value) 
{
    mxmlElementSetAttr(element,attribute,value);
}




//The only non boilerplate code around in this program is this function
void serve_hello_page(struct mg_connection *conn)
{
    char output[1000];
    mg_send_header(conn,"Content-Type","text/html; charset=utf-8");
    mg_printf_data(conn, "%s", "<!DOCTYPE html>");
    //This literally prints into the html document


    /*Let's generate some html, we could have avoided the
     * xml parser and just spat out pure html with mg_printf_data
     * e.g. mg_printF_data(conn,"%s", "<html>hello</html>") */

    //...But xml is cleaner, here we go:
            dom html=mxmlNewElement(MXML_NO_PARENT,"html");
                dom head=c(html,"head");
                    dom meta=c(head,"meta");
                    sa(meta,"charset","utf-8");
                dom body=c(html,"body");
                    t(body,"Hello, world<<"); //The < is auto escaped, neat!
                    c(body,"br");
                    t(body,"Fred ate bred");    
                dom table=c(body,"table");
                sa(table,"border","1");

                //populate the table via sqlite
                rc = sqlite3_exec(db, "SELECT * from myCoolTable", callback, table, &zErrMsg);
                if( rc!=SQLITE_OK )
                {
                    fprintf(stderr, "SQL error: %s\n", zErrMsg);
                    sqlite3_free(zErrMsg);
                }

            mxmlSaveString (html,output,1000,  MXML_NO_CALLBACK);
            mg_printf_data(conn, "%s", output);
            mxmlDelete(html); 
}

//sqlite callback
static int callback(void * custom, int argc, char **argv, char **azColName)
{
    //this function is executed for each row
    dom table=(dom)custom;

    dom tr=c(table,"tr");
    dom td;
    int i;
    for(i=0; i<argc; i++)
    {
        td=c(tr,"td");
        if (argv[i])
            t(td, argv[i]);
        else
            t(td, "NULL");

        printf("%s == %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    }
     printf("\n");
     return 0;
}


static int event_handler(struct mg_connection *conn, enum mg_event ev)
{
    if (ev == MG_AUTH)
    {
        return MG_TRUE;   // Authorize all requests
    }
    else if (ev == MG_REQUEST)
    {
        if (!strcmp(conn->uri, "/hello"))
        {
            serve_hello_page(conn);
            return MG_TRUE;   // Mark as processed
        }
    }
    return MG_FALSE;  // Rest of the events are not processed

}

int main(void)
{
    struct mg_server *server = mg_create_server(NULL, event_handler);
    //mg_set_option(server, "document_root", "."); //prevent dir listing and auto file serving
    //TODO can I allow file listing without dir listing in a specified directory?
    mg_set_option(server, "listening_port", "8080");


    rc = sqlite3_open("db.sqlite3", &db); 

    if( rc )
    {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        return(1);
    }

    printf("Server is running on port 8080!\n");
    for (;;)
    {
        mg_poll_server(server, 1000);  // Infinite loop, Ctrl-C to stop
    }
    mg_destroy_server(&server);
    sqlite3_close(db);

    return 0;
}




/*
 * useful stuff:
 * mg_send_file(struct mg_connection *, const char *path); - serve the file at *path*/

Zum Schluss kompilieren!

Lassen Sie uns kompilieren. cd in Ihren Hauptordner und führen Sie diese aus:

gcc -c main.c
gcc -c mongoose.c
gcc -c sqlite3.c
gcc -o server.out main.o mongoose.o sqlite3.o -ldl -lpthread -lmxml -L . 

Führen Sie nun server.out mit /server.out Aus und navigieren Sie zu localhost:8080/hello

Erledigt :)

2
Hello World

Ich vermute, dass mehrere eingebettete Systeme (z. B. Router, Drucker usw.) über einen C++ - gesteuerten Webserver verfügen.

Insbesondere können Sie eine HTTP-Serverbibliothek wie libonion verwenden, um einem C- oder C++ - Programm einige Webfunktionen hinzuzufügen oder um einen Light-Server mit einer Webschnittstelle zu entwickeln.

Einige Leute codieren ihren Webserver oder ihre HTTP-Schnittstelle in Ocaml mit Ocsigen . Nicht jede Web-Sache ist PHP. Und mit FastCGI können Sie eine dynamische Webverarbeitung in/zu Ihrer Anwendung durchführen.