it-swarm.it

Il C ++ può essere utilizzato come linguaggio di sviluppo Web sul lato server?

Mi piacerebbe entrare nello sviluppo web usando C++ come "linguaggio di scripting" sul lato server. La mia infrastruttura server è basata su * nix, quindi lo sviluppo web in C++ su Azure non è applicabile e anche ASP.NET C++/CLI non è applicabile.

Separato dalle applicazioni CGI legacy, lo sviluppo Web può essere eseguito utilizzando C++?

34
Scott Davies

Assolutamente.

Ci sono anche diversi framework per svilupparli, inclusi Wt , cppcms , CSP e altri. L'implementazione della linea principale di FastCGI è in C e supporta direttamente diverse lingue , incluso C++.

Qualsiasi linguaggio di programmazione in grado di analizzare le stringhe può essere utilizzato in CGI o in un servlet. Qualsiasi linguaggio in grado di implementare associazioni con librerie C può anche essere usato per sviluppare moduli per server compatibili ISAPI o Apache.

Non è particolarmente facile in C++ e i buoni motori di template sono pochi e rari, ma può essere fatto.

Naturalmente, la questione se questa sia una buona idea è completamente un'altra questione. :)

Nota: I principali siti Web come Amazon.com, eBay e Google usano C++ per parti della loro infrastruttura. Renditi conto, tuttavia, che Google utilizza il C++ solo per sistemi critici per la velocità e che Amazon.com è passato relativamente di recente da LISP (il che ha fatto arrabbiare parte del suo personale senior :).

Facebook precedentemente compilato PHP a C++, ma il loro compilatore HipHop (scritto in parte in C++) da allora è stato rielaborato come una macchina virtuale bytecode.

56
greyfade

Perchè no?

Il sito di incontri OkCupid è creato con C++. Probabilmente ci sono altri esempi.

C'è anche un toolkit ispirato a Qt per lo sviluppo di applicazioni Web con C++ chiamato Wt .

18
Vitor Py

Se stai pianificando di scrivere la tua applicazione web in C++, sarebbe totalmente inutile interfacciarlo come CGI.

Il mio consiglio sarebbe di costruirlo in modo asincrono usando ASIO (I/O asincrono). In questo modo puoi creare un servizio web estremamente veloce (combinalo con nginx come proxy inverso e server statico per i migliori effetti); Combinalo con una libreria di modelli come Wt e sei pronto a servire decine di migliaia di richieste al secondo da un singolo server.

Se questa sia un'alternativa pratica al framework web linguistico dinamico è un altro problema.

11
vartec

La risposta breve è: TUTTO può essere usato per scrivere una pagina Web a condizione che possa leggere l'input, scrivere output interpretabile ed è eseguibile dal server web.

Tecnicamente, qualsiasi linguaggio può essere utilizzato come script CGI a condizione che:

  1. Interpreta tutti gli input e l'ambiente come presentati dal server
  2. Output in un linguaggio di markup noto (generalmente html)
  3. Può essere eseguito dal server

Ci sono anche altri modi. Perl ha la capacità di essere costruito come un wrapper attorno al codice c/c ++, fungendo da strato di interpretazione tra i due (e questo non include i moduli Perl che sono stati compilati come C).

9
Avatar_Squadron

all'inizio, era abbastanza comune: i primi siti Web su cui ho lavorato alla fine degli anni '90 erano estensioni ISAPI scritte in C++ e funzionavano abbastanza bene.

7
Steven A. Lowe

Sembra che anche Microsoft pensi di poterlo fare. Dai un'occhiata a Casablanca che è un nuovo set di strumenti per (sembra) Azure usando C++.

Casablanca è un progetto per iniziare a esplorare come supportare al meglio gli sviluppatori C++ che vogliono sfruttare il cambiamento radicale nell'architettura software rappresentata dal cloud computing.

Ecco cosa ottieni con Casablanca:

  • Supporto per l'accesso REST servizi dal codice nativo su Windows Vista, Windows 7 e Windows 8 Consumer Preview fornendo collegamenti C++ asincroni a HTTP, JSON e URI
  • Un SDK di estensione di Visual Studio per aiutarti a scrivere codice lato client HTTP C++ nella tua app Metro 8 di Windows
  • Supporto per la scrittura di codice nativo REST per Azure, inclusa l'integrazione di Visual Studio
  • Pratiche librerie per l'accesso all'archiviazione BLOB e code di Azure da client nativi come funzionalità PaaS (Platform-as-a-Service) di prima classe
  • Un modello coerente e potente per la composizione di operazioni asincrone basato sulle funzionalità di C++ 11
  • Un'implementazione in C++ del modello di programmazione basato sull'attore di Erlang
  • Una serie di campioni e documentazione
5
gbjbaanb

Per PHP puoi scrivere le tue estensioni C/C++ e ottenere buoni benefici in questo modo. Se avessi avuto una parte molto intensiva della CPU della mia applicazione Web probabilmente avrei creato una piccola libreria C++ che ha scaricato quell'elaborazione sull'estensione e quindi ha restituito il risultato a PHP e quindi a PHP lo invia al browser.

L'altra cosa che la gente spesso non considera è scaricare una certa elaborazione della CPU sul lato client, ad es. JavaScript/jQuery. Se ho un web server, potrei aver bisogno di una CPU a 3 GHz per eseguire un'elaborazione intensiva della CPU per una particolare funzione (forse un po 'di elaborazione dei dati). La mia azienda paga ogni mese per quel server per mantenerlo attivo. Se voglio aumentare le operazioni per 100 utenti simultanei che eseguono contemporaneamente l'attività intensiva della CPU, forse ho bisogno di più CPU e server, aumentando i costi per la mia attività. Se scarico quell'attività intensiva della CPU sul lato client, ogni utente che visita il sito Web può eseguire la propria elaborazione sui dati e non devo aumentare la capacità del mio server risparmiando così denaro.

Dopotutto con la potenza collettiva di oltre 100 desktop/tablet/cellulari che eseguono l'elaborazione per te, questo è molto più potente del tuo server seduto in un datacenter da qualche parte che costa ai tuoi soldi ogni mese per continuare a funzionare. Potenzialmente, tutto ciò che il tuo server farebbe sarebbe recuperare i dati dal database, servire il contenuto e un po 'di pre/post elaborazione e validazione dei dati prima di archiviarli nuovamente nel database. Ovviamente non dovresti rendere il codice lato client troppo intenso per la CPU che potrebbe bloccare/congelare l'interfaccia utente del browser web, potresti lanciare una richiesta AJAX sul server, recuperare i dati e quindi elaborare i dati in modo asincrono client -side, lasciando l'interfaccia utente del browser web completamente utilizzabile.

2
zuallauz

Sì, può essere usato. Gli altri hanno menzionato vari approcci. Ecco il mio approccio. Il vantaggio è che è totalmente portatile e autonomo, tutte le librerie scelte dipendono solo da ANSI C. L'impostazione richiede solo il kernel Linux e un compilatore C (E le cose ovvie come Busybox, bash, ecc.) (O Windows e un compilatore), non sono necessarie librerie extra, nessuna grande installazione di fantasia.

Il risultato è un singolo programma che è sia un web server sia un generatore di pagine dinamico (sostituisce sia "Apache" che "php"), inoltre avrà accesso al database tramite sqlite.

Librerie utilizzate:

  • Mongoose - Server http
  • Sqlite - Database SQL
  • MiniXML - Semplifica la generazione di pagine dinamiche. un po 'come Javascript createElement

Il resto di questa risposta è una guida di installazione completa per Linux. Sia SQlite che MiniXML sono opzionali, ma la guida copre l'installazione completa. Spetta a te commentare le parti non necessarie se sei interessato a disabilitare sqlite o MiniXML.

1. Scarica le 3 librerie

2. Prepara la tua cartella

  • Crea una cartella vuota (la chiameremo la cartella principale)
  • Inserisci i seguenti file:
    • Da sqlite tar.gz: sqlite3.c , sqlite3.h
    • Da Mongoose Zip: mongoose.c , mongoose.h
    • Dal mxml tar.gz: mxml.h

3. Compila mxml

Potresti aver notato che manca mxml.c, questo perché abbiamo bisogno di creare una libreria mxml statica. Vai alla cartella in cui è stato scaricato mxml tar.gz ed esegui:

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.

Una volta terminata la compilazione, verranno generati molti file, l'unico file che ci interessa è libmxml.a, copia quel file nella cartella principale.

3.1 Doppio controllo

Verificare che la cartella principale abbia quanto segue:

  • Per la mangusta: mongoose.c, mongoose.h
  • Per mxml: libmxml.a, mxml.h
  • per sqlite: sqlite.c, sqlite.h

4. main.c

Creiamo il programma attuale, creiamo un main.c file nella cartella principale, ecco uno scheletro per iniziare.

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

Infine, compilando!

Compiliamo. cd nella tua cartella principale ed esegui questi:

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 . 

Ora esegui server.out con /server.out e vai a localhost:8080/hello

Fatto :)

2
Hello World

Immagino che diversi sistemi embedded (ad es. Router, stampanti, ...) abbiano un web server guidato da C++.

In particolare, è possibile utilizzare alcune librerie di server HTTP come libonion per aggiungere alcune funzionalità web ad alcuni programmi C o C++ o per sviluppare un server leggero con qualche interfaccia web.

Alcune persone stanno codificando il loro server Web o la loro interfaccia HTTP in Ocaml usando Ocsigen . Non ogni cosa web è PHP. E con FastCGI potresti elaborare una dinamica elaborazione web nella/alla tua applicazione.