C ++ peut-il être utilisé comme langage de développement Web côté serveur? [fermé]

34

J'aimerais entrer dans le développement Web en utilisant C ++ comme "langage de script" côté serveur. Mon infrastructure de serveur étant * nix, le développement Web en C ++ sur Azure ne s'applique pas et C ++ / CLI ASP.NET ne s'applique pas non plus.

En dehors des applications CGI traditionnelles, le développement Web peut-il être réalisé en C ++?

Scott Davies
la source
33
Bien sûr que c'est possible , la question est; est-ce pratique ?
Ed S.
Voir cette question sur stackoverflow.com.
Kevin Cline
24
Vous pourriez utiliser assembly comme langage côté serveur si vous le vouliez.
Channel72
8
Ou même Brainf * ck si ,are .sont redirigés vers un socket.
dan04
4
Cela me rappelle d'horribles souvenirs du premier projet Web auquel j'ai participé. Les passerelles CGI vers le code C. Je frémis encore quand j'y pense! :-)
Brian Knoblauch Le

Réponses:

56

Absolument.

Il existe même plusieurs cadres pour les développer, notamment Wt , cppcms , CSP , etc. L'implémentation principale de FastCGI est en C et supporte directement plusieurs langages , dont le C ++.

Tout langage de programmation pouvant analyser des chaînes peut être utilisé dans CGI ou dans une servlet. Tout langage pouvant implémenter des liaisons avec des bibliothèques C peut également être utilisé pour développer des modules pour des serveurs compatibles ISAPI ou Apache.

Ce n'est pas particulièrement facile en C ++, et de bons moteurs de templates sont rares, mais cela peut être fait.

Bien sûr, la question de savoir s’il s’agit d’une bonne idée est un tout autre problème. :)

Remarque: les principaux sites Web tels qu'Amazon.com, eBay et Google utilisent le C ++ pour certaines parties de leur infrastructure. Sachez cependant que Google n'utilise le C ++ que pour les systèmes critiques en matière de vitesse et qu'Amazon.com n'est que relativement récemment sorti de Lisp (ce qui a provoqué la colère de certains de leurs cadres supérieurs :).

Facebook avait auparavant compilé PHP en C ++, mais leur compilateur HipHop (écrit en partie en C ++) a depuis été réaménagé en machine virtuelle bytecode.

dégraissage
la source
2
+1 Pour citer différents cadres. Vous devriez ajouter qu'il est courant que les (très) grandes applications Web soient alimentées par c ++ (et d'autres langages): amazon.com, google.com, maintenant facebook.com via hiphop, etc.
Klaim
7
@ Klaim: C'est courant, mais ce n'est en aucun cas la règle. L'architecture d'Amazon était historiquement basée sur Lisp et n'a été réécrite que récemment en C ++. L'architecture de Google implique Java, Python et d'autres presque aussi souvent que le C ++, le tout pour diverses raisons. Facebook utilise maintenant uniquement le hiphop, car ils ont découvert que PHP ne s'adaptait pas. :)
Greyfade
4
Je suis d'accord, mais je voulais dire que ce sont toujours des exemples bien connus d'utilisation du C ++ - pour répondre directement au titre de la question d'origine.
Klaim
1
Le problème de la mise à l'échelle de @johannes Facebook provient du fait qu'ils doivent maintenir un ordre de grandeur supérieur à celui des serveurs, en raison notamment des performances médiocres d'un script PHP optimisé. La mise à l'échelle linéaire n'est tout simplement pas suffisante pour une infrastructure de cette taille. Mais rappelez-vous que l'approche "rien partagé" n'est pas exclusive à PHP. C et C ++ peuvent le faire aussi.
Greyfade
1
@amar La chose est qu'il y a peu de retour sauf dans les 0,1% d'applications qui ont besoin de cette performance brute. Vous pouvez servir un tiers du temps dans la plupart des autres langues avec un bon support de pile Web. Les banques, les annonceurs sur le Web, etc., ont tous une grande envergure sans recourir au C ++. Même Facebook. Gazouillement. StackOverflow. Tous le font dans les langues de niveau supérieur. Il est là pour rester mais il ne va pas redevenir majoritaire. Probablement jamais.
Rig
18

Pourquoi pas?

Le site de rencontres OkCupid est créé avec C ++. Il y a probablement d'autres exemples.

Il existe également une boîte à outils inspirée de Qt pour le développement d'applications Web avec C ++ appelée Wt .

Vitor Py
la source
11
"Pourquoi pas "? Parce que c'est beaucoup plus facile d'utiliser un langage qui prend davantage en charge ce genre de choses.
Ed S.
5
@Ed S. Comme I et greyfade l’ont souligné, il existe des cadres de développement d’applications Web en C ++.
Vitor Py
2
Oui, mais encore une fois, sont-ils aussi faciles à utiliser que les frameworks les plus couramment utilisés? Honnêtement, je demande: je ne suis pas un développeur Web et je ne les ai jamais utilisées, mais quelque chose me dit qu'elles ne sont probablement pas aussi matures ni aussi largement utilisées que leurs homologues ruby ​​/ python / PHP, par exemple.
Ed S.
3
@EdS: Ni Ruby ni Python n’ont démarré avec les frameworks Web. En fait, il a fallu une décennie pour que ceux-ci apparaissent. Les frameworks sont la simple conséquence d'un nombre suffisant de personnes souhaitant utiliser le langage X pour résoudre le problème Y. La même chose pourrait se produire pour C ++. Les principales raisons pour lesquelles cela n'a pas été le cas: le C ++ n'est pas géré, prend beaucoup de temps à compiler et a une barrière d'entrée plus élevée en général.
back2dos
1
@ back2dos: Qui a dit que l'une ou l'autre langue avait été développée pour le Web? Je n'ai certainement pas. J'ai utilisé le terme "support".
Ed S.
11

Si vous envisagez d’écrire votre application Web en C ++, il serait totalement inutile de l’interfacer en tant que CGI.

Ma suggestion serait de le construire de manière asynchrone en utilisant ASIO (Asynchronous I / O). Avec cela, vous pouvez créer un service Web ultra rapide (combinez-le avec nginx en tant que serveur proxy inverse et statique pour obtenir les meilleurs effets); Combinez cela avec une bibliothèque de modèles comme Wt et vous êtes prêt à traiter des dizaines de milliers de requêtes par seconde à partir d'un serveur unique.

La question de savoir s'il s'agit d'une alternative pratique au framework web de langage dynamique est un autre problème.

vartec
la source
9

En bref, ANYTHING peut être utilisé pour écrire une page Web, à condition qu’il puisse lire l’entrée, écrire une sortie interprétable et qu’il soit exécutable par le serveur Web.

Techniquement, toute langue peut être utilisée comme script CGI à condition:

  1. Interprète toutes les entrées et l'environnement tels que présentés par le serveur
  2. Sorties dans un langage de balisage connu (généralement HTML)
  3. Peut être exécuté par le serveur

Il y a aussi d'autres moyens. Perl a la capacité d'être construit comme un wrapper autour du code c / c ++, agissant comme une couche d'interprétation entre les deux (et cela n'inclut pas les modules Perl qui sont compilés à plat en C).

Avatar_Squadron
la source
7

au début, c'était assez courant - les premiers sites Web sur lesquels j'ai travaillé à la fin des années 90 étaient des extensions ISAPI écrites en C ++, et ils fonctionnaient assez bien.

Steven A. Lowe
la source
3
isapi.dll quelqu'un?
rouge-saleté
ou ATLServer - atlserver.codeplex.com
gbjbaanb
5

Il semble que Microsoft le pense aussi. Découvrez Casablanca qui est un nouvel ensemble d’outils pour Azure (apparemment) utilisant C ++.

Casablanca est un projet visant à explorer le meilleur moyen de soutenir les développeurs C ++ qui souhaitent tirer parti de l’évolution radicale de l’architecture logicielle représentée par le cloud computing.

Voici ce que vous obtenez avec Casablanca:

  • Prise en charge de l'accès aux services REST à partir du code natif sous Windows Vista, Windows 7 et Windows 8 Consumer Preview en fournissant des liaisons C ++ asynchrones à HTTP, JSON et URI
  • Kit de développement logiciel (SDK) Visual Studio pour vous aider à écrire du code côté client HTTP C ++ dans votre application de style métro Windows 8
  • Prise en charge de l'écriture de code REST natif pour Azure, y compris l'intégration de Visual Studio
  • Bibliothèques pratiques pour accéder au stockage d'objets blob et de files d'attente Azure à partir de clients natifs en tant que fonctionnalité PaaS (Platform-as-a-Service) de premier ordre
  • Un modèle cohérent et puissant pour la composition d'opérations asynchrones basé sur les fonctionnalités de C ++ 11
  • Une implémentation C ++ du modèle de programmation basé sur l'acteur Erlang
  • Un ensemble d'échantillons et de documentation
gbjbaanb
la source
2

Pour PHP, vous pouvez écrire vos propres extensions C / C ++ et obtenir ainsi de bons avantages en termes de performances. Si mon application Web nécessitait beaucoup de ressources en temps processeur, je créerais probablement une petite bibliothèque C ++ qui aurait déchargé ce traitement sur l'extension, puis renvoyé le résultat à PHP, qui le renvoie ensuite au navigateur.

L’autre chose que les gens ne considèrent pas souvent est de décharger certains traitements de la CPU du côté client, par exemple JavaScript / jQuery. Si j'ai un serveur Web, j'ai peut-être besoin d'un processeur 3Ghz pour effectuer un traitement gourmand en ressources CPU pour une fonction particulière (peut-être un traitement de données). Mon entreprise paie de l'argent pour ce serveur chaque mois pour le maintenir en fonctionnement. Si je souhaite augmenter les opérations pour 100 utilisateurs simultanés exécutant simultanément cette tâche gourmande en ressources processeur, j'ai peut-être besoin de plusieurs processeurs et serveurs, ce qui augmente les coûts pour mon entreprise. Si je délègue cette tâche gourmande en ressources processeur du côté client, chaque utilisateur qui visite le site Web peut effectuer son propre traitement des données et je n'ai pas à augmenter la capacité de mon serveur, ce qui me permet d'économiser de l'argent.

Après tout, avec la puissance collective de plus de 100 ordinateurs de bureau / tablettes / mobiles, le traitement pour vous est beaucoup plus puissant que votre serveur installé dans un centre de données, ce qui coûte de l'argent à votre entreprise chaque mois. Potentiellement, tout ce que votre serveur ferait serait de récupérer des données de la base de données, de fournir du contenu, ainsi qu'un peu de pré / post traitement et de validation des données avant de les stocker dans la base de données. Évidemment, vous ne feriez pas un code client trop gourmand en ressources processeur qui bloquerait / gèlerait l'interface utilisateur du navigateur Web, vous pourriez envoyer une requête AJAX au serveur, récupérer les données puis traiter les données de manière asynchrone côté client, en laissant le site Web. -interface utilisateur complètement utilisable.

zuallauz
la source
2

Oui, il peut être utilisé. Les autres ont mentionné diverses approches. Voici ma propre approche. L’avantage est qu’elle est totalement portable et autonome. Toutes les bibliothèques sélectionnées dépendent uniquement de ANSI C. Pour le configurer, il suffit de disposer du noyau Linux et d’un compilateur C et un compilateur), pas de bibliothèques supplémentaires sont nécessaires, pas de grandes installations de fantaisie.

Le résultat est un programme unique qui est à la fois un serveur Web et un générateur de page dynamique (remplace à la fois "apache" et "php"), il disposera également d'un accès à la base de données via sqlite.

Bibliothèques utilisées:

  • Mongoose - Serveur Http
  • Sqlite - Base de données SQL
  • MiniXML - Facilite la génération de pages dynamiques. un peu comme JavascriptcreateElement

Le reste de cette réponse est un guide complet de configuration pour Linux. SQlite et MiniXML sont facultatifs, mais le guide couvre l’installation complète. Il vous appartient de commenter les parties inutiles si vous souhaitez désactiver sqlite ou MiniXML.

1. Téléchargez les 3 bibliothèques

2. Préparez votre dossier

  • Créez un dossier vide (nous l'appellerons le dossier principal)
  • Mettez les fichiers suivants dedans:
    • De la sq.gite tar.gz: sqlite3.c , sqlite3.h
    • Du zip Mongoose: mongoose.c , mongoose.h
    • Du mxml tar.gz: mxml.h

3. Compiler le mxml

Vous avez peut-être remarqué que mxml.c est manquant, car nous devons créer une bibliothèque statique mxml. Accédez au dossier de téléchargement du fichier .txz tar.gz et effectuez les opérations suivantes:

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.

Une fois la compilation terminée, de nombreux fichiers seront générés. Le seul fichier qui nous intéresse est de libmxml.acopier ce fichier dans le dossier principal.

3.1 Doublecheck

Vérifiez que le dossier principal présente les éléments suivants:

  • Pour la mangouste: mongoose.c, mongoose.h
  • Pour le mxml: libmxml.a, mxml.h
  • pour sqlite: sqlite.c, sqlite.h

4. main.c

Créons le programme actuel, créons un main.cfichier dans le dossier principal, voici un squelette pour vous aider à démarrer.

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

Enfin, compiler!

Compilons. cddans votre dossier principal et exécutez ceux-ci:

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 . 

Maintenant, exécutez server.out avec /server.outet naviguez jusqu’àlocalhost:8080/hello

Terminé :)

Bonjour le monde
la source
@ Hey: Merci d'avoir signalé cette alternative à Mongoose, je préfère toujours les projets menés par la communauté. Je vais probablement remplacer Mongoose par Civetweb dans ma réponse après l'avoir soigneusement testé.
Bonjour le monde
0

Je suppose que plusieurs systèmes embarqués (par exemple, routeurs, imprimantes, ...) ont un serveur Web piloté par C ++.

En particulier, vous pouvez utiliser une bibliothèque de serveur HTTP telle que libonion pour ajouter des fonctionnalités Web à certains programmes C ou C ++, ou pour développer un serveur léger avec une interface Web.

Certaines personnes codent leur serveur Web ou leur interface HTTP dans Ocaml à l’aide de Ocsigen . Tous les sites Web ne sont pas PHP. Et avec FastCGI, vous pouvez bénéficier d’ un traitement Web dynamique dans / pour votre application.

Basile Starynkevitch
la source