Можно ли использовать C ++ в качестве языка веб-разработки на стороне сервера? [закрыто]

34

Я хотел бы заняться веб-разработкой, используя C ++ в качестве «языка сценариев» на стороне сервера. Моя серверная инфраструктура основана на * nix, поэтому веб-разработка на C ++ на Azure неприменима, а C ++ / CLI ASP.NET также не применима.

Отдельно от унаследованных CGI-приложений, можно ли заниматься веб-разработкой с использованием C ++?

Скотт Дэвис
источник
33
Конечно, это возможно , вопрос в том, это практично ?
Эд С.
Смотрите этот вопрос на stackoverflow.com.
Кевин Клайн
24
Вы можете использовать ассемблер в качестве языка на стороне сервера, если вы так склонны.
Channel72
8
Или даже Brainf * ск , если ,будут .перенаправлены на сокет.
dan04
4
Это возвращает ужасные воспоминания о первом веб-проекте, в котором я участвовал. CGI-шлюзы в C-код. Я все еще дрожу, когда думаю об этом! :-)
Брайан Кноблаух

Ответы:

56

Абсолютно.

Есть еще несколько структур для их развития, в том числе Wt , CppCMS , ПСУ и другие. Основная реализация FastCGI написана на C и напрямую поддерживает несколько языков , включая C ++.

Любой язык программирования, который может анализировать строки, может использоваться в CGI или в сервлете. Любой язык, который может реализовывать привязки с библиотеками C, также может использоваться для разработки модулей для ISAPI- или Apache-совместимых серверов.

Это не особенно легко в C ++, и хороших шаблонизаторов очень мало, но это можно сделать.

Конечно, вопрос о том, является ли это хорошей идеей, является совершенно другим вопросом. :)

Обратите внимание: крупные сайты, такие как Amazon.com, eBay и Google, используют C ++ для части своей инфраструктуры. Поймите, однако, что Google использует C ++ только для систем, критичных к скорости, а Amazon.com сравнительно недавно отказался от Lisp (что вызвало недовольство некоторых из их старших сотрудников :).

Ранее Facebook компилировал PHP в C ++, но с тех пор их компилятор HipHop (частично написанный на C ++) был переоборудован в виртуальную машину с байт-кодом.

greyfade
источник
2
+1 За цитирование различных рамок. Вы должны добавить, что для (очень) крупных веб-приложений обычно используется c ++ (и другие языки): amazon.com, google.com, теперь facebook.com через хип-хоп и т. Д.
Klaim
7
@Klaim: Это распространено, но это ни в коем случае не правило. Архитектура Amazon была исторически основана на Лиспе и только недавно была переписана на C ++. Архитектура Google включает Java, Python и другие почти так же часто, как C ++, и все по разным причинам. Facebook использует сейчас только хип-хоп, потому что они обнаружили, что PHP не масштабируется. :)
Greyfade
4
Я согласен, но я имел в виду, что они все еще являются хорошо известными примерами использования C ++ - чтобы ответить прямо на оригинальное название вопроса.
Klaim
1
@johannes Проблема масштабирования Facebook связана с тем, что им приходится обслуживать на порядок больше серверов, чем необходимо, особенно из-за низкой производительности оптимизированного PHP-скрипта. Линейное масштабирование просто недостаточно для такой большой инфраструктуры. Но помните, что подход «ничего не поделился» не является эксклюзивным для PHP. C и C ++ тоже могут это делать.
Greyfade
1
@amar Дело в том, что отдача невелика, за исключением 0,1% приложений, которым требуется такая грубая производительность. Вы могли бы служить в 1/3 времени на большинстве других языков с хорошей поддержкой веб-стека. Банки, веб-рекламодатели и т. Д. Обслуживают в широком масштабе, не прибегая к C ++. Даже Фейсбук. Twitter. Переполнение стека. Все делают это на языках более высокого уровня. Его здесь, чтобы остаться, но он не собирается снова стать большинством. Наверное, когда-либо.
Рог
18

Почему бы нет?

Сайт знакомств OkCupid создан на C ++. Есть, вероятно, другие примеры.

Есть также вдохновленный Qt инструментарий для разработки веб-приложений на C ++ под названием Wt .

Vitor Py
источник
11
"Почему бы и нет "? Потому что гораздо проще использовать язык, который имеет больше поддержки для такого рода вещей.
Эд С.
5
@Ed S. Как я и Greyfade указали, есть рамки для разработки веб-приложений на C ++.
Vitor Py
2
Да, но опять же, они так же просты в использовании, как и более часто используемые фреймворки? Я честно спрашиваю, я не веб-разработчик, и я никогда не использовал их, но что-то подсказывает мне, что они, вероятно, не настолько зрелы или широко используются, как (например) их аналоги ruby ​​/ python / PHP.
Эд С.
3
@EdS .: Ни Ruby, ни Python не начинали с веб-фреймворков. На самом деле это заняло десятилетие. Фреймворки являются простым следствием того, что достаточно много людей хотят использовать язык X для решения проблемы Y. То же самое может случиться с C ++. Основные причины, почему этого не произошло: C ++ не управляется, требует много времени для компиляции и имеет более высокий входной барьер в целом.
back2dos
1
@ back2dos: Кто сказал, что любой язык был разработан с учетом веба? Я конечно не сделал. Я использовал термин «поддержка».
Эд С.
11

Если вы планируете написать свое веб-приложение на C ++, было бы совершенно бесполезно использовать его как CGI.

Мое предложение состояло бы в том, чтобы построить это асинхронное использование ASIO (Асинхронный ввод / вывод). При этом вы можете создать невероятно быстрый веб-сервис (в сочетании с nginx в качестве обратного прокси-сервера и статического сервера для достижения наилучших результатов); Объедините это с библиотекой шаблонов, такой как Wt, и вы будете готовы обслуживать десятки тысяч запросов в секунду с одного сервера.

Является ли это практической альтернативой динамическим языковым веб-фреймворкам, это другой вопрос.

Vartec
источник
9

Краткий ответ: НИЧЕГО можно использовать для написания веб-страницы, при условии, что она может читать входные данные, записывать интерпретируемые выходные данные и может выполняться веб-сервером.

Технически, любой язык может быть использован в качестве CGI-скрипта при условии, что он:

  1. Интерпретирует все входные данные и среду как представлено сервером
  2. Выводы на известном языке разметки (обычно html)
  3. Может быть запущен на сервере

Есть и другие способы тоже. Perl может быть построен как обертка вокруг кода c / c ++, выступая в качестве интерпретирующего слоя между ними (и это не относится к модулям perl, которые полностью скомпилированы как C).

Avatar_Squadron
источник
7

в начале это было довольно распространенным явлением - первые веб-сайты, над которыми я работал в конце 1990-х, были расширениями ISAPI, написанными на C ++, и они работали довольно хорошо.

Стивен А. Лоу
источник
3
isapi.dll кто-нибудь?
красная грязь
или ATLServer - atlserver.codeplex.com
gbjbaanb
5

Похоже, Microsoft думает, что может тоже. Проверьте Casablanca, который представляет собой новый набор инструментов для (кажется) Azure с использованием C ++.

Casablanca - это проект, который начинает изучать, как лучше всего поддерживать разработчиков на C ++, которые хотят воспользоваться преимуществами радикального сдвига в архитектуре программного обеспечения, который представляет облачные вычисления.

Вот что вы получаете с Касабланкой:

  • Поддержка доступа к службам REST из собственного кода в Windows Vista, Windows 7 и Windows 8 Consumer Preview путем предоставления асинхронных привязок C ++ к HTTP, JSON и URI
  • SDK расширения Visual Studio, чтобы помочь вам написать клиентский код на C ++ HTTP в вашем приложении в стиле Metro для Windows 8
  • Поддержка написания REST для Azure с собственным кодом, включая интеграцию Visual Studio
  • Удобные библиотеки для доступа к хранилищу BLOB-объектов и очередей Azure с собственных клиентов в качестве первоклассной функции «платформа как услуга» (PaaS)
  • Согласованная и мощная модель для составления асинхронных операций, основанная на возможностях C ++ 11
  • Реализация модели программирования Erlang на основе акторов на C ++
  • Набор образцов и документации
gbjbaanb
источник
2

Для PHP вы можете написать свои собственные расширения C / C ++ и таким образом получить хорошую производительность. Если бы в моем веб-приложении была действительно интенсивная загрузка процессора, я бы, вероятно, создал бы небольшую библиотеку C ++, которая передавала бы эту обработку в расширение, а затем возвращала результат обратно в PHP, а затем PHP выводил его в браузер.

Другая вещь, которую люди не часто рассматривают, - это разгрузка определенной обработки ЦП на стороне клиента, например, JavaScript / jQuery. Если у меня есть веб-сервер, мне может потребоваться процессор с частотой 3 ГГц, чтобы выполнять интенсивную обработку ЦП для определенной функции (возможно, для обработки некоторых данных). Моя компания платит деньги за этот сервер каждый месяц, чтобы он работал. Если я хочу увеличить масштабы операций для 100 одновременно работающих пользователей, одновременно выполняющих эту задачу, интенсивно использующую ЦП, то, возможно, мне потребуется несколько ЦП и серверов, что увеличит затраты для моего бизнеса. Если я перенесу эту задачу, интенсивно использующую ЦП, на клиентскую сторону, то каждый пользователь, посещающий веб-сайт, может самостоятельно обрабатывать данные, и мне не нужно увеличивать возможности моего сервера, что экономит мои деньги.

В конце концов, благодаря совокупной мощности более 100 настольных компьютеров / планшетов / мобильных устройств, выполняющих обработку для вас, это намного больше энергии, чем ваш сервер, находящийся в центре обработки данных, где каждый месяц стоит деньги на ведение бизнеса. Потенциально тогда все, что будет делать ваш сервер, будет извлекать данные из базы данных, обслуживать контент и немного до / после обработки и проверки данных перед их сохранением в базе данных. Очевидно, что вы не сделаете код на стороне клиента слишком интенсивным ЦП, который может заблокировать / заморозить пользовательский интерфейс веб-браузера, вы можете запустить AJAX-запрос к серверу, получить данные и затем обработать данные асинхронно на стороне клиента, оставив Интернет -браузер UI полностью пригоден для использования.

zuallauz
источник
2

Да, это можно использовать. Другие упоминали различные подходы. Вот мой собственный подход. Преимущество состоит в том, что он является полностью переносимым и автономным, все выбранные библиотеки зависят только от ANSI C. Для его настройки требуется только ядро ​​Linux и компилятор C (и такие очевидные вещи, как Busybox, bash и т. Д.) (Или Windows и компилятор), никаких дополнительных библиотек не требуется, никаких необычных огромных установок.

В результате получается одна программа, которая одновременно является веб-сервером и динамическим генератором страниц (заменяет как «apache», так и «php»), а также будет иметь доступ к базе данных через sqlite.

Использованные библиотеки:

  • Mongoose - Http сервер
  • Sqlite - база данных SQL
  • MiniXML - упрощает динамическое создание страниц. вроде как JavascriptcreateElement

Остальная часть этого ответа представляет собой полное руководство по настройке для Linux. И SQlite, и MiniXML не являются обязательными, но в руководстве описана полная установка. Вы можете закомментировать ненужные части, если вы заинтересованы в отключении sqlite или MiniXML.

1. Загрузите 3 библиотеки

2. Подготовьте свою папку

  • Создайте пустую папку (назовем ее основной папкой)
  • Поместите в него следующие файлы:
    • Из sqlite tar.gz: sqlite3.c , sqlite3.h
    • Из почтового индекса Мангуст: mongoose.c , mongoose.h
    • Из mxml tar.gz: mxml.h

3. Скомпилируйте mxml

Возможно, вы заметили, что mxml.c отсутствует, потому что нам нужно создать статическую библиотеку mxml. Перейдите в папку, куда был загружен файл mxml tar.gz, и выполните:

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.

После завершения компиляции будет создано много файлов, единственный интересующий нас libmxml.aфайл - скопируйте этот файл в основную папку.

3.1 Двойная проверка

Убедитесь, что в главной папке есть следующее:

  • Для мангусты: mongoose.c, mongoose.h
  • Для mxml: libmxml.a, mxml.h
  • для sqlite: sqlite.c, sqlite.h

4. main.c

Давайте создадим саму программу, создадим main.cфайл в главной папке, вот вам скелет для начала.

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

Наконец, компиляция!

Давайте скомпилируем. cdв вашу основную папку и выполните эти:

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 . 

Теперь выполните server.out с помощью /server.outи перейдите кlocalhost:8080/hello

Выполнено :)

Привет, мир
источник
1
github.com/bel2125/civetweb
Привет,
@Hey: Спасибо за указание на эту альтернативу Mongoose, я всегда предпочитаю проекты, управляемые сообществом. Вероятно, я заменю Mongoose на Civetweb в своем ответе после того, как тщательно его протестирую.
Привет, мир,
0

Я предполагаю, что несколько встроенных систем (например, маршрутизаторы, принтеры, ...) имеют некоторый веб-сервер, управляемый C ++.

В частности, вы можете использовать некоторую библиотеку HTTP-сервера, такую ​​как libonion, чтобы добавить некоторые веб-возможности в какую-либо программу на C или C ++ или разработать легкий сервер с некоторым веб-интерфейсом.

Некоторые люди кодируют свой веб-сервер или HTTP-интерфейс в Ocaml, используя Ocsigen . Не каждая вещь в Интернете - это PHP. А с FastCGI вы можете выполнять динамическую веб-обработку в вашем приложении.

Василий Старынкевич
источник