Kann C ++ als serverseitige Webentwicklungssprache verwendet werden? [geschlossen]

34

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

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

Scott Davies
quelle
33
Natürlich ist es möglich , die Frage ist; ist es praktisch ?
Ed S.
Siehe diese Frage auf stackoverflow.com.
Kevin Cline
24
Sie könnten Assembly als serverseitige Sprache verwenden, wenn Sie dies wünschen.
Channel72
8
Oder sogar Brainf * ck , wenn ,sich .an eine Steckdose umgeleitet.
dan04
4
Dies weckt schreckliche Erinnerungen an das erste Webprojekt, an dem ich beteiligt war. CGI-Gateways zu C-Code. Ich schaudere immer noch, wenn ich darüber nachdenke! :-)
Brian Knoblauch

Antworten:

56

Absolut.

Es gibt sogar mehrere Gerüste sie für die Entwicklung, einschließlich Wt , cppcms , CSP und andere. Die Hauptimplementierung von FastCGI erfolgt 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 gute Template-Engines gibt es nur wenige, aber es kann getan werden.

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

Hinweis: 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 abgewechselt hat (was einige seiner leitenden Angestellten verärgerte :).

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

greyfade
quelle
2
+1 Zum Zitieren verschiedener Frameworks. Sie sollten hinzufügen, dass es für (sehr) große Web-Apps üblich ist, mit C ++ (und anderen Sprachen) betrieben zu werden: amazon.com, google.com, jetzt facebook.com über HipHop usw.
Klaim
7
@Klaim: Es ist üblich, aber es ist keineswegs die Regel. Die Architektur von Amazon basierte historisch auf Lisp und wurde erst kürzlich in C ++ umgeschrieben. Die Architektur von Google umfasst Java, Python und andere Programme aus verschiedenen Gründen fast so häufig wie C ++. Facebook nutzt derzeit nur HipHop, da festgestellt wurde, dass PHP nicht skaliert. :)
greyfade
4
Ich stimme zu, aber ich meinte, dass sie immer noch bekannte Beispiele für die Verwendung von C ++ sind - um den ursprünglichen Fragentitel direkt zu beantworten.
Klaim am
1
Das Skalierungsproblem von @johannes Facebook beruht auf der Tatsache, dass sie eine Größenordnung mehr Server warten müssen, als dies sonst erforderlich wäre, insbesondere aufgrund der schlechten Leistung eines optimierten PHP-Skripts. Die lineare Skalierung ist für eine so große Infrastruktur einfach nicht gut genug. Denken Sie jedoch daran, dass der Ansatz "Shared Nothing" nicht nur für PHP gilt. C und C ++ können das auch.
greyfade
1
@amar Die Sache ist, dass es nur in 0,1% der Apps, die diese rohe Leistung benötigen, eine geringe Rendite gibt. Sie können in den meisten anderen Sprachen in einem Drittel der Zeit mit einer guten Webstack-Unterstützung arbeiten. Banken, Web-Werbetreibende usw. bedienen massiv, ohne auf C ++ zurückzugreifen. Sogar Facebook. Twitter. Paketüberfluss. Alle machen das in höheren Sprachen. Es ist hier, um zu bleiben, aber es wird nicht wieder die Mehrheit werden. Wahrscheinlich jemals.
Rig
18

Warum nicht?

Die OkCupid- Dating-Site 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 .

Vitor Py
quelle
11
"Warum nicht "? Weil es viel einfacher ist, eine Sprache zu verwenden, die diese Art von Dingen besser unterstützt.
Ed S.
5
@Ed S. Wie ich und greyfade betonten, gibt es Frameworks für die Entwicklung von Webanwendungen mit C ++.
Vitor Py
2
Ja, aber sind sie genauso einfach zu verwenden wie häufig verwendete Frameworks? Ich frage ehrlich, ich bin kein Webentwickler und habe sie nie benutzt, aber irgendetwas sagt mir, dass sie wahrscheinlich nicht so ausgereift oder weit verbreitet sind wie (zum Beispiel) ihre Ruby / Python / PHP-Gegenstücke.
Ed S.
3
@EdS .: Weder Ruby noch Python haben mit Web-Frameworks begonnen. Tatsächlich dauerte es ein Jahrzehnt, bis diese erschienen. Die Frameworks sind die bloße Konsequenz von genügend Leuten, die Sprache X für Problem Y verwenden möchten. Dasselbe könnte für C ++ passieren. Hauptgründe, warum dies nicht der Fall war: C ++ wird nicht verwaltet, die Kompilierung nimmt einige Zeit in Anspruch und weist im Allgemeinen eine höhere Eintrittsbarriere auf.
back2dos
1
@ back2dos: Wer hat gesagt, dass beide Sprachen im Hinblick auf das Web entwickelt wurden? Ich habe es sicherlich nicht getan. Ich habe den Begriff "Unterstützung" verwendet.
Ed S.
11

Wenn Sie vorhaben, Ihre Webanwendung in C ++ zu schreiben, wäre es reine Verschwendung, sie dann als CGI-Schnittstelle zu verwenden.

Mein Vorschlag wäre, es asynchron mit ASIO (Asynchronous I / O) 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). Wenn Sie dies mit einer Vorlagenbibliothek wie Wt kombinieren, können Sie Zehntausende Anfragen pro Sekunde von einem einzelnen Server aus bearbeiten.

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

vartec
quelle
9

Die kurze Antwort lautet: ALLES kann zum Schreiben einer Webseite verwendet werden, vorausgesetzt, es kann die Eingabe lesen, eine interpretierbare Ausgabe schreiben und es kann vom Webserver ausgeführt werden.

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

  1. Interpretiert alle vom Server bereitgestellten Eingaben und Umgebungen
  2. Ausgabe in einer bekannten Auszeichnungssprache (in der Regel HTML)
  3. Kann vom Server ausgeführt werden

Es gibt auch andere Möglichkeiten. Perl kann als Wrapper für C / C ++ - Code erstellt werden, der als Interpretationsebene zwischen beiden fungiert (ohne Perl-Module, die vollständig als C kompiliert sind).

Avatar_Squadron
quelle
7

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 recht gut.

Steven A. Lowe
quelle
3
isapi.dll jemand?
Red-Dirt
oder ATLServer - atlserver.codeplex.com
gbjbaanb
5

Offenbar glaubt Microsoft, dass dies auch möglich ist. Schauen Sie sich Casablanca an , ein neues Toolset für (es scheint) Azure unter Verwendung von C ++.

Casablanca ist ein Projekt, das sich mit der Frage befasst, wie C ++ - Entwickler am besten unterstützt werden können, die von der radikalen Veränderung der Softwarearchitektur, die Cloud Computing darstellt, profitieren möchten.

Folgendes erhalten Sie mit Casablanca:

  • Unterstützung für den Zugriff auf REST-Dienste über systemeigenen 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-App im Metro-Stil schreiben können
  • Unterstützung für das Schreiben von REST für Azure mit systemeigenem Code, einschließlich der Visual Studio-Integration
  • Praktische Bibliotheken für den Zugriff auf Azure-Blob- und Warteschlangenspeicher von systemeigenen Clients aus als erstklassige PaaS-Funktion (Platform-as-a-Service)
  • Ein konsistentes und leistungsstarkes Modell zum Erstellen asynchroner Operationen auf der Basis von C ++ 11-Features
  • Eine C ++ - Implementierung des Erlang-Actor-basierten Programmiermodells
  • Eine Reihe von Beispielen und Dokumentationen
gbjbaanb
quelle
2

Für PHP können Sie Ihre eigenen C / C ++ - Erweiterungen schreiben und auf diese Weise gute Performance-Vorteile erzielen. Wenn ich einen wirklich CPU-intensiven Teil meiner Webanwendung hätte, würde ich wahrscheinlich eine kleine C ++ - Bibliothek erstellen, die diese Verarbeitung in die Erweiterung verlagert und das Ergebnis dann an PHP zurückgibt und dann vom PHP an den Browser ausgibt.

Das andere, was die Leute nicht oft in Betracht ziehen, ist, bestimmte CPU-Prozesse auf die Client-Seite zu verlagern, z. B. JavaScript / jQuery. Wenn ich einen Webserver habe, brauche ich möglicherweise eine 3 GHz-CPU, um eine CPU-intensive Verarbeitung für eine bestimmte Funktion durchzuführen (möglicherweise etwas Datenverarbeitung). Mein Unternehmen zahlt monatlich Geld für diesen Server, um ihn am Laufen zu halten. Wenn ich Vorgänge 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, wodurch sich die Kosten für mein Unternehmen erhöhen. Wenn ich diese CPU-intensive Aufgabe auf die Client-Seite verlagere, kann jeder Benutzer, der die Website besucht, die Daten selbst verarbeiten, und ich muss meine Serverleistung nicht erhöhen, wodurch ich Geld einsparen kann.

Schließlich ist die Gesamtleistung von über 100 Desktops / Tablets / Mobilgeräten, die die Verarbeitung für Sie erledigen, um ein Vielfaches höher als die Leistung, die Ihr Server in einem Rechenzentrum erbringt, das Ihr Geschäftsgeld jeden Monat kostet, um weiter zu arbeiten. In diesem Fall würde Ihr Server möglicherweise nur Daten aus der Datenbank abrufen, Inhalte bereitstellen und ein wenig Vor- / Nachbearbeitung und Validierung der Daten durchführen, bevor Sie sie wieder in der Datenbank speichern. Offensichtlich würden Sie den clientseitigen Code nicht zu rechenintensiv machen, wodurch die Benutzeroberfläche des Webbrowsers blockiert / eingefroren werden könnte. Sie könnten eine AJAX-Anforderung an den Server auslösen, die Daten abrufen und die Daten dann asynchron clientseitig verarbeiten und das Web verlassen -Browser-Benutzeroberfläche vollständig verwendbar.

zuallauz
quelle
2

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

Das Ergebnis ist ein einzelnes Programm, das sowohl ein Webserver als auch ein dynamischer Seitengenerator ist (Ersetzt sowohl "apache" als auch "php"). Es wird auch über SQLite auf die Datenbank zugreifen können.

Verwendete Bibliotheken:

  • Mungo - HTTP-Server
  • SQLite - SQL-Datenbank
  • MiniXML - Erleichtert die dynamische Seitenerstellung. Art wie JavascriptcreateElement

Der Rest dieser Antwort ist eine vollständige Installationsanleitung für Linux. Sowohl SQlite als auch MiniXML sind optional, das Handbuch behandelt jedoch die vollständige Installation. Sie können die nicht benötigten Teile auskommentieren, 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
    • Vom Mungo-Reißverschluss: mongoose.c , mongoose.h
    • Aus dem mxml tar.gz: mxml.h

3. Kompilieren Sie mxml

Möglicherweise haben Sie bemerkt, dass mxml.c fehlt. Dies liegt daran, dass wir eine statische mxml-Bibliothek erstellen müssen. Gehen 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, diese Datei in den Hauptordner zu kopieren.

3.1 Doppelcheck

Ü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, erstellen Sie eine main.cDatei im Hauptordner, hier ist ein Skelett für Sie, um loszulegen.

#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*/

Endlich kompilieren!

Lassen Sie uns kompilieren. cdin deinen Hauptordner und führe 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 aus /server.outund navigieren Sie zulocalhost:8080/hello

Getan :)

Hallo Welt
quelle
@ Hey: Danke, dass du auf diese Mungo-Alternative hingewiesen hast. Ich bevorzuge immer Community-Projekte. Ich werde Mungo in meiner Antwort wahrscheinlich durch Civetweb ersetzen, nachdem ich es gründlich getestet habe.
Hallo Welt
0

Ich vermute, dass einige eingebettete Systeme (z. B. Router, Drucker, ...) einen C ++ - gesteuerten Webserver haben.

Insbesondere könnten 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 dynamische Web-Verarbeitung in / in Ihrer Anwendung durchführen.

Basile Starynkevitch
quelle