¿Se puede usar C ++ como lenguaje de desarrollo web del lado del servidor? [cerrado]

34

Me gustaría entrar en el desarrollo web usando C ++ como el "lenguaje de programación" en el lado del servidor. La infraestructura de mi servidor está basada en * nix, por lo que el desarrollo web en C ++ en Azure no es aplicable y C ++ / CLI ASP.NET tampoco es aplicable.

Aparte de las aplicaciones CGI heredadas, ¿se puede realizar el desarrollo web con C ++?

Scott Davies
fuente
33
Por supuesto que es posible , la pregunta es; ¿Es práctico ?
Ed S.
Vea esta pregunta en stackoverflow.com.
Kevin Cline
24
Podrías usar el ensamblado como un lenguaje del lado del servidor si estuvieras tan dispuesto.
Channel72
8
O incluso Brainf * ck si ,se .redirige a una toma de corriente.
dan04
44
Esto trae recuerdos horribles del primer proyecto web en el que estuve involucrado. Puertas de enlace CGI al código C. ¡Todavía me estremezco cuando lo pienso! :-)
Brian Knoblauch

Respuestas:

56

Absolutamente.

Incluso hay varios marcos para desarrollarlos, incluidos Wt , cppcms , CSP y otros. La implementación principal de FastCGI está en C y admite directamente varios lenguajes , incluido C ++.

Cualquier lenguaje de programación que pueda analizar cadenas puede usarse en CGI o un servlet. Cualquier lenguaje que pueda implementar enlaces con bibliotecas C también se puede usar para desarrollar módulos para servidores compatibles con ISAPI o Apache.

No es particularmente fácil en C ++, y los buenos motores de plantillas son pocos y distantes entre sí, pero se puede hacer.

Por supuesto, la cuestión de si es una buena idea es algo completamente distinto. :)

Tenga en cuenta: los principales sitios web como Amazon.com, eBay y Google usan C ++ para partes de su infraestructura. Sin embargo, tenga en cuenta que Google solo usa C ++ para sistemas críticos para la velocidad, y Amazon.com solo recientemente se alejó de Lisp (lo que enfureció a algunos de sus altos funcionarios :).

Facebook compiló anteriormente PHP a C ++, pero su compilador HipHop (escrito en parte en C ++) se ha modificado como una máquina virtual de código de bytes.

Greyfade
fuente
2
+1 Por citar varios marcos. Debe agregar que es común que (muy) grandes aplicaciones web funcionen con c ++ (y otros idiomas): amazon.com, google.com, ahora facebook.com a través de hiphop, etc.
Klaim
77
@Klaim: Es común, pero de ninguna manera es la regla. La arquitectura de Amazon se basó históricamente en Lisp y solo se reescribió recientemente en C ++. La arquitectura de Google involucra a Java, Python y otros casi tan a menudo como C ++, todo por varias razones. Facebook solo usa hiphop ahora porque descubrieron que PHP no escala. :)
greyfade
44
Estoy de acuerdo, pero quise decir que todavía son ejemplos bien conocidos del uso de C ++, para responder directamente el título original de la pregunta.
Klaim
1
El problema de escalado de @johannes Facebook se debe al hecho de que tienen que mantener un orden de magnitud de más servidores de los que son necesarios, específicamente debido al bajo rendimiento de un script PHP optimizado. El escalado lineal simplemente no es lo suficientemente bueno para una infraestructura tan grande. Pero recuerde que el enfoque de "nada compartido" no es exclusivo de PHP. C y C ++ también pueden hacer eso.
greyfade
1
@amar La cosa es que hay poco retorno, excepto en el 0.1% de las aplicaciones que necesitan ese rendimiento bruto. Podría servir en 1/3 del tiempo en la mayoría de los otros idiomas con un buen soporte de pila web. Los bancos, los anunciantes web, etc., sirven a gran escala sin recurrir a C ++. Incluso Facebook Gorjeo. Desbordamiento de pila. Todos lo hacen en idiomas de nivel superior. Está aquí para quedarse, pero no volverá a ser mayoría. Probablemente alguna vez.
Aparejo
18

Por qué no?

El sitio de citas OkCupid se crea con C ++. Probablemente hay otros ejemplos.

También hay un kit de herramientas inspirado en Qt para desarrollar aplicaciones web con C ++ llamado Wt .

Vitor Py
fuente
11
"¿Por qué no "? Porque es mucho más fácil usar un lenguaje que tenga más soporte para este tipo de cosas.
Ed S.
55
@Ed S. Como I y greyfade señalaron, existen marcos para desarrollar aplicaciones web con C ++.
Vitor Py
2
Sí, pero de nuevo, ¿son tan fáciles de usar como los frameworks más utilizados? Honestamente, no soy un desarrollador web y nunca los he usado, pero algo me dice que probablemente no sean tan maduros o ampliamente utilizados como (por ejemplo) sus contrapartes ruby ​​/ python / PHP.
Ed S.
3
@EdS .: Ni Ruby ni Python comenzaron con frameworks web. De hecho, tardó una década en aparecer. Los marcos son la mera consecuencia de que suficientes personas quieran usar el lenguaje X para el problema Y. Lo mismo podría suceder con C ++. Principales razones por las que no lo hizo: C ++ no se gestiona, lleva mucho tiempo compilar y tiene una barrera de entrada más alta en general.
back2dos
1
@ back2dos: ¿Quién dijo que cualquiera de los dos idiomas fue desarrollado con la web en mente? Ciertamente no lo hice. Usé el término "soporte".
Ed S.
11

Si planea escribir su aplicación web en C ++, sería un desperdicio total interactuar como CGI.

Mi sugerencia sería construirlo de forma asíncrona utilizando ASIO (E / S asíncrona). Con eso, puede crear un servicio web increíblemente rápido (combine con nginx como un servidor de proxy inverso y estadísticas para obtener los mejores efectos); Combine eso con la biblioteca de plantillas como Wt y estará listo para atender decenas de miles de solicitudes por segundo desde un único servidor.

Si esta es una alternativa práctica al marco web de lenguaje dinámico es otro tema.

vartec
fuente
9

La respuesta corta es que CUALQUIER COSA puede usarse para escribir una página web, siempre que pueda leer la entrada, escribir una salida interpretable y que el servidor web pueda ejecutarla.

Técnicamente, cualquier lenguaje se puede usar como un script CGI siempre que:

  1. Interpreta todas las entradas y el entorno presentados por el servidor.
  2. Salidas en un lenguaje de marcado conocido (generalmente html)
  3. Puede ser ejecutado por el servidor

También hay otras formas también. Perl tiene la capacidad de construirse como una envoltura alrededor del código c / c ++, actuando como una capa de interpretación entre los dos (y esto no incluye los módulos perl que están compilados como C).

Avatar_Squadron
fuente
7

Al principio, era bastante común: los primeros sitios web en los que trabajé a fines de la década de 1990 fueron extensiones ISAPI escritas en C ++, y funcionaron bastante bien.

Steven A. Lowe
fuente
3
isapi.dll alguien?
Red-dirt
o ATLServer - atlserver.codeplex.com
gbjbaanb
5

Parece que Microsoft cree que también puede hacerlo. Echa un vistazo a Casablanca, que es un nuevo conjunto de herramientas para (parece) Azure usando C ++.

Casablanca es un proyecto para comenzar a explorar la mejor forma de apoyar a los desarrolladores de C ++ que desean aprovechar el cambio radical en la arquitectura de software que representa la computación en la nube.

Esto es lo que obtienes con Casablanca:

  • Soporte para acceder a servicios REST desde código nativo en Windows Vista, Windows 7 y Windows 8 Consumer Preview al proporcionar enlaces asíncronos de C ++ a HTTP, JSON y URI
  • Un SDK de extensión de Visual Studio para ayudarlo a escribir el código del lado del cliente C ++ HTTP en su aplicación estilo Metro de Windows 8
  • Soporte para escribir REST de código nativo para Azure, incluida la integración de Visual Studio
  • Bibliotecas convenientes para acceder al almacenamiento de colas y blobs de Azure desde clientes nativos como una función de plataforma como servicio (PaaS) de primera clase
  • Un modelo consistente y potente para componer operaciones asincrónicas basadas en características de C ++ 11
  • Una implementación en C ++ del modelo de programación basado en actores Erlang
  • Un conjunto de muestras y documentación.
gbjbaanb
fuente
2

Para PHP, puede escribir sus propias extensiones C / C ++ y obtener buenos beneficios de rendimiento de esa manera. Si tuviera una parte realmente intensiva de la CPU de mi aplicación web, probablemente haría una pequeña biblioteca C ++ que descargó ese procesamiento a la extensión y luego devolvió el resultado al PHP y luego el PHP lo envía al navegador.

La otra cosa que la gente no suele considerar es descargar cierto procesamiento de la CPU al lado del cliente, por ejemplo, JavaScript / jQuery. Si tengo un servidor web, es posible que necesite una CPU de 3 GHz para realizar un procesamiento intensivo de la CPU para una función en particular (tal vez algún procesamiento de datos). Mi empresa paga dinero por ese servidor cada mes para mantenerlo en funcionamiento. Si deseo ampliar las operaciones para 100 usuarios concurrentes que ejecutan esa tarea intensiva de CPU al mismo tiempo, entonces tal vez necesito varias CPU y servidores, lo que aumenta el costo para mi negocio. Si descargo esa tarea intensiva de la CPU al lado del cliente, entonces cada usuario que visita el sitio web puede hacer su propio procesamiento de los datos y no tengo que aumentar la capacidad de mi servidor, por lo tanto, me ahorra dinero.

Después de todo, con todo el poder colectivo de más de 100 computadoras de escritorio / tabletas / móviles que realizan el procesamiento por usted, eso es mucho más poder que su servidor ubicado en un centro de datos en algún lugar que le cuesta dinero a su negocio cada mes para seguir funcionando. Potencialmente, todo lo que su servidor estaría haciendo sería recuperar datos de la base de datos, servir contenido y un poco de procesamiento previo / posterior y validación de los datos antes de almacenarlos nuevamente en la base de datos. Obviamente, no haría que el código del lado del cliente fuera demasiado intensivo para la CPU, lo que podría bloquear / congelar la interfaz de usuario del navegador web, podría disparar una solicitud AJAX al servidor, recuperar los datos y luego procesar los datos asincrónicamente del lado del cliente, dejando la web -Interfaz de navegador completamente utilizable.

zuallauz
fuente
2

Sí, se puede usar. Los otros han mencionado varios enfoques. Aquí está mi propio enfoque. La ventaja es que es totalmente portátil y autónomo, todas las bibliotecas seleccionadas solo dependen de ANSI C. La configuración solo requiere el kernel de Linux y un compilador de C (y las cosas obvias como Busybox, bash, etc.) (o Windows y un compilador), no se necesitan bibliotecas adicionales, ni grandes instalaciones sofisticadas.

El resultado es un único programa que es a la vez un servidor web y un generador de páginas dinámicas (Sustituye "apache" y "php"), también tendrá acceso a la base de datos a través de sqlite.

Bibliotecas utilizadas:

  • Mangosta - servidor HTTP
  • SQLite - Base de datos SQL
  • MiniXML: facilita la generación dinámica de páginas. algo así como Javascript'screateElement

El resto de esta respuesta es una guía de configuración completa para Linux. Tanto SQlite como MiniXML son opcionales, pero la guía cubre la instalación completa. Depende de usted comentar las partes no necesarias si está interesado en deshabilitar sqlite o MiniXML.

1. Descargue las 3 bibliotecas

2. Prepare su carpeta

  • Cree una carpeta vacía (la llamaremos la carpeta principal)
  • Pon los siguientes archivos en él:
    • Desde el sqlite tar.gz: sqlite3.c , sqlite3.h
    • Desde el zip de Mangosta: mongoose.c , mongoose.h
    • Desde el mxml tar.gz: mxml.h

3. Compilar mxml

Es posible que haya notado que falta mxml.c, esto se debe a que necesitamos crear una biblioteca estática de mxml. Vaya a la carpeta donde se descargó el mxml tar.gz y realice:

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 vez finalizada la compilación, se generarán muchos archivos, el único archivo que nos interesa es libmxml.acopiar ese archivo en la carpeta principal.

3.1 Doublecheck

Verifique que la carpeta principal tenga lo siguiente:

  • Para la mangosta: mongoose.c, mongoose.h
  • Para mxml: libmxml.a, mxml.h
  • para sqlite: sqlite.c, sqlite.h

4. main.c

Creemos el programa real, cree un main.carchivo en la carpeta principal, aquí hay un esqueleto para que pueda comenzar.

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

Finalmente, compilando!

Vamos a compilar cda su carpeta principal y ejecute estos:

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 . 

Ahora, ejecute server.out con /server.outy navegue hastalocalhost:8080/hello

Hecho :)

Hola Mundo
fuente
@Hey: Gracias por señalar esta alternativa de Mongoose, siempre prefiero los proyectos impulsados ​​por la comunidad. Probablemente reemplazaré Mongoose con Civetweb en mi respuesta después de probarlo a fondo.
Hola mundo, el
0

Supongo que varios sistemas integrados (por ejemplo, enrutadores, impresoras, ...) tienen algún servidor web controlado por C ++.

En particular, podría usar alguna biblioteca de servidor HTTP como libonion para agregar algunas capacidades web a algún programa C o C ++, o para desarrollar un servidor ligero con alguna interfaz web.

Algunas personas están codificando su servidor web o su interfaz HTTP en Ocaml usando Ocsigen . No todas las cosas web son PHP. Y con FastCGI podría realizar un procesamiento web dinámico en / a su aplicación.

Basile Starynkevitch
fuente