O C ++ pode ser usado como uma linguagem de desenvolvimento web do lado do servidor? [fechadas]

34

Eu gostaria de entrar no desenvolvimento da Web usando C ++ como a "linguagem de script" no lado do servidor. Minha infraestrutura de servidor é baseada em * nix, portanto, o desenvolvimento da Web em C ++ no Azure não é aplicável e o C ++ / CLI ASP.NET também não é aplicável.

Separado dos aplicativos CGI herdados, o desenvolvimento da Web pode ser feito usando C ++?

Scott Davies
fonte
33
Claro que é possível , a questão é; é prático ?
Ed S.
Veja esta pergunta em stackoverflow.com.
Kevin cline #
24
Você pode usar o assembly como um idioma do lado do servidor, se assim o desejar.
Channel72
8
Ou mesmo Brainf * ck se ,são .são redirecionados para um soquete.
dan04
4
Isso traz de volta lembranças horríveis do primeiro projeto da Web em que estive envolvido. Gateways CGI para código C. Eu ainda tremo quando penso nisso! :-)
Brian Knoblauch 02/03

Respostas:

56

Absolutamente.

Existem até várias estruturas para desenvolvê-las, incluindo Wt , cppcms , CSP e outras. A implementação da linha principal do FastCGI é em C e suporta diretamente várias linguagens , incluindo C ++.

Qualquer linguagem de programação que possa analisar cadeias de caracteres pode ser usada em CGI ou em um servlet. Qualquer linguagem que possa implementar ligações com bibliotecas C também pode ser usada para desenvolver módulos para servidores compatíveis com ISAPI ou Apache.

Não é particularmente fácil em C ++, e os bons mecanismos de modelagem são poucos e distantes entre si, mas isso pode ser feito.

Obviamente, a questão de saber se é uma boa ideia é outra questão. :)

Observe: sites importantes como Amazon.com, eBay e Google usam C ++ para partes de sua infraestrutura. Perceba, no entanto, que o Google usa apenas C ++ para sistemas de velocidade crítica, e a Amazon.com recentemente se afastou recentemente do Lisp (o que irritou alguns de seus funcionários seniores :).

O Facebook anteriormente compilou o PHP em C ++, mas seu compilador HipHop (escrito em parte em C ++) foi reformulado desde então como uma máquina virtual de bytecode.

desvanecer-se
fonte
2
+1 Para citar várias estruturas. Você deve adicionar que é comum que aplicativos da Web (muito) grandes
usem
7
@Klaim: É comum, mas não é de modo algum a regra. A arquitetura da Amazon era historicamente baseada em Lisp e apenas recentemente reescrita em C ++. A arquitetura do Google envolve Java, Python e outros quase tão frequentemente quanto o C ++, tudo por vários motivos. O Facebook só usa o hiphop agora porque descobriu que o PHP não é escalável. :)
greyfade
4
Concordo, mas quis dizer que eles ainda são exemplos bem conhecidos de uso de C ++ - para responder diretamente ao título da pergunta original.
Klaim
1
@johannes O problema de dimensionamento do Facebook decorre do fato de que eles precisam manter uma ordem de magnitude em mais servidores do que o necessário, especificamente devido ao baixo desempenho de um script PHP otimizado. A escala linear simplesmente não é boa o suficiente para uma infraestrutura tão grande. Mas lembre-se de que a abordagem "nada compartilhado" não é exclusiva do PHP. C e C ++ também podem fazer isso.
Greyfade 17/05
1
@amar O problema é que há pouco retorno, exceto nos 0,1% de aplicativos que precisam desse desempenho bruto. Você pode servir em 1/3 do tempo na maioria dos outros idiomas, com um bom suporte de pilha da web. Bancos, anunciantes da web, etc., todos atendem em grande escala sem recorrer ao C ++. Até o Facebook. Twitter. StackOverflow. Todos fazem isso em idiomas de nível superior. Está aqui para ficar, mas não se tornará a maioria novamente. Provavelmente sempre.
Rig
18

Por que não?

O site de namoro OkCupid é criado com C ++. Provavelmente existem outros exemplos.

Há também um kit de ferramentas inspirado no Qt para desenvolver aplicativos da Web com C ++ chamado Wt .

Vitor Py
fonte
11
"Porque não "? Porque é muito mais fácil usar uma linguagem que tenha mais suporte para esse tipo de coisa.
Ed S.
5
@ Ed S. Como eu e o greyfade apontamos, existem estruturas para o desenvolvimento de aplicativos da web com C ++.
Vitor Py
2
Sim, mas novamente, eles são tão fáceis de usar quanto as estruturas mais usadas? Estou sinceramente perguntando, não sou desenvolvedor web e nunca os usei, mas algo me diz que eles provavelmente não são tão maduros ou amplamente usados ​​como (por exemplo) seus colegas ruby ​​/ python / PHP.
Ed S.
3
@ Eds .: Nem Ruby nem Python começaram com frameworks web. De fato, levou uma década para que eles aparecessem. As estruturas são a mera consequência de um número suficiente de pessoas que desejam usar a linguagem X para o problema Y. O mesmo poderia acontecer com o C ++. Principais razões pelas quais isso não aconteceu: o C ++ não é gerenciado, leva muito tempo para ser compilado e possui uma barreira de entrada mais alta em geral.
precisa saber é o seguinte
1
@ back2dos: Quem disse que um dos idiomas foi desenvolvido com a web em mente? Eu certamente não. Eu usei o termo "suporte".
Ed S.
11

Se você planeja escrever seu aplicativo Web em C ++, seria um desperdício total fazer a interface como CGI.

Minha sugestão seria construí-lo assíncrono usando ASIO (E / S assíncrona). Com isso, você pode criar um serviço da Web incrivelmente rápido (combine com o nginx como um servidor de proxy reverso e estático para obter melhores efeitos); Combine isso com a biblioteca de modelos como a Wt e você estará pronto para atender a dezenas de milhares de solicitações por segundo em um único servidor.

Se essa é uma alternativa prática à estrutura da web de linguagem dinâmica é outra questão.

vartec
fonte
9

A resposta curta é: QUALQUER COISA pode ser usada para escrever uma página da Web, desde que seja possível ler a entrada, gravar saída interpretável e ser executável pelo servidor da Web.

Tecnicamente, qualquer idioma pode ser usado como um script CGI, desde que:

  1. Interpreta todas as entradas e ambiente, conforme apresentado pelo servidor
  2. Saídas em uma linguagem de marcação conhecida (geralmente html)
  3. Pode ser executado pelo servidor

Também existem outras maneiras. O Perl pode ser construído como um invólucro em torno do código c / c ++, atuando como uma camada de interpretação entre os dois (e isso não inclui os módulos perl que são compilados como C).

Avatar_Squadron
fonte
7

no começo, era bastante comum - os primeiros sites em que trabalhei no final dos anos 90 foram extensões ISAPI escritas em C ++ e funcionaram muito bem.

Steven A. Lowe
fonte
3
isapi.dll alguém?
Vermelho-sujidade
ou ATLServer - atlserver.codeplex.com
gbjbaanb
5

Parece que a Microsoft acha que pode também. Confira Casablanca, que é um novo conjunto de ferramentas (aparentemente) do Azure usando C ++.

O Casablanca é um projeto para começar a explorar a melhor forma de apoiar os desenvolvedores de C ++ que desejam tirar vantagem da mudança radical na arquitetura de software que a computação em nuvem representa.

Aqui está o que você ganha com Casablanca:

  • Suporte para acessar serviços REST a partir de código nativo no Windows Vista, Windows 7 e Windows 8 Consumer Preview, fornecendo ligações C ++ assíncronas para HTTP, JSON e URIs
  • Um SDK de extensão do Visual Studio para ajudá-lo a escrever o código do lado do cliente HTTP C ++ no seu aplicativo estilo Metro do Windows 8
  • Suporte para escrever REST de código nativo para o Azure, incluindo a integração do Visual Studio
  • Bibliotecas convenientes para acessar o armazenamento de blobs e filas do Azure de clientes nativos como um recurso de PaaS (Platform as a Service) de primeira classe
  • Um modelo consistente e poderoso para compor operações assíncronas com base nos recursos do C ++ 11
  • Uma implementação em C ++ do modelo de programação baseado em ator Erlang
  • Um conjunto de amostras e documentação
gbjbaanb
fonte
2

Para PHP, você pode escrever suas próprias extensões C / C ++ e obter bons benefícios de desempenho dessa maneira. Se eu tivesse uma parte realmente intensiva da CPU do meu aplicativo Web, provavelmente criaria uma pequena biblioteca C ++ que transferisse esse processamento para a extensão e depois retornaria o resultado ao PHP e o PHP o enviaria ao navegador.

A outra coisa que as pessoas geralmente não consideram é transferir certos processamentos da CPU para o lado do cliente, por exemplo, JavaScript / jQuery. Se eu tiver um servidor da Web, talvez seja necessário uma CPU de 3Ghz para fazer um processamento intensivo da CPU para uma função específica (talvez algum processamento de dados). Minha empresa está pagando dinheiro por esse servidor todos os meses para mantê-lo funcionando. Se eu quiser expandir as operações para 100 usuários simultâneos executando essa tarefa intensiva de CPU ao mesmo tempo, talvez seja necessário várias CPUs e servidores, aumentando o custo para os meus negócios. Se eu descarregar essa tarefa intensiva da CPU para o lado do cliente, cada usuário que visitar o site poderá fazer seu próprio processamento nos dados e não preciso aumentar a capacidade do servidor, economizando dinheiro.

Afinal de contas, com o poder coletivo de mais de 100 desktops / tablets / celulares fazendo o processamento para você, é muito mais poderoso do que o seu servidor sentado em um datacenter em algum lugar que custa o dinheiro da sua empresa todos os meses para continuar funcionando. Potencialmente, então tudo o que seu servidor faria seria recuperar dados do banco de dados, exibir conteúdo e um pouco de processamento pré / pós e validação dos dados antes de armazenar novamente no banco de dados. Obviamente, você não tornaria o código do lado do cliente muito intensivo da CPU, o que poderia bloquear / congelar a interface do navegador da web, você poderia disparar uma solicitação AJAX para o servidor, recuperar os dados e depois processá-los de forma assíncrona, deixando a web UI do navegador completamente utilizável.

zuallauz
fonte
2

Sim, pode ser usado. Os outros mencionaram várias abordagens. Aqui está a minha própria abordagem. A vantagem é que é totalmente portátil e independente, todas as bibliotecas selecionadas dependem apenas do ANSI C. A configuração requer apenas o Linux Kernel e um compilador C (e coisas óbvias como Busybox, bash etc.) (ou Windows e um compilador), nenhuma biblioteca extra é necessária, nenhuma instalação grande e sofisticada.

O resultado é um programa único, que é um servidor da Web e um gerador de páginas dinâmico (substitui "apache" e "php"), mas também terá acesso ao banco de dados via sqlite.

Bibliotecas usadas:

  • Mongoose - servidor HTTP
  • Sqlite - Banco de Dados SQL
  • MiniXML - Facilita a geração dinâmica de páginas. tipo como JavascriptcreateElement

O restante desta resposta é um guia completo de configuração para Linux. O SQlite e o MiniXML são opcionais, mas o guia cobre a instalação completa. Cabe a você comentar as partes não necessárias se estiver interessado em desativar o sqlite ou o MiniXML.

1. Faça o download das 3 bibliotecas

2. Prepare sua pasta

  • Crie uma pasta vazia (a chamaremos de pasta principal)
  • Coloque os seguintes arquivos nele:
    • No sqlite tar.gz: sqlite3.c , sqlite3.h
    • No zip do Mongoose: mongoose.c , mongoose.h
    • No mxml tar.gz: mxml.h

3. Compile mxml

Você deve ter notado que o mxml.c está ausente, porque precisamos criar uma biblioteca estática de mxml. Vá para a pasta em que o mxml tar.gz foi baixado e execute:

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.

Quando a compilação terminar, muitos arquivos serão gerados, o único arquivo de interesse para nós é libmxml.acopiá-lo para a pasta principal.

3.1 Doublecheck

Verifique se a pasta principal possui o seguinte:

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

4. main.c

Vamos criar o programa atual, criar um main.carquivo na pasta principal, aqui está um esqueleto para você começar.

#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 compilar. cdpara sua pasta principal e execute:

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 . 

Agora, execute server.out com /server.oute navegue paralocalhost:8080/hello

Feito :)

Olá Mundo
fonte
@ Hey: Obrigado por apontar essa alternativa do Mongoose, eu sempre prefiro projetos voltados para a comunidade. Provavelmente vou substituir o Mongoose pelo Civetweb na minha resposta depois de testá-lo completamente.
Olá Mundo
0

Eu acho que vários sistemas embarcados (por exemplo, roteadores, impressoras, ...) têm algum servidor Web orientado a C ++.

Em particular, você pode usar alguma biblioteca de servidores HTTP como a libonion para adicionar alguns recursos da web a algum programa C ou C ++ ou desenvolver um servidor leve com alguma interface da web.

Algumas pessoas estão codificando seu servidor Web ou sua interface HTTP no Ocaml usando o Ocsigen . Nem toda coisa da web é PHP. E com o FastCGI, você pode realizar um processamento dinâmico da web em / para seu aplicativo.

Basile Starynkevitch
fonte