web-dev-qa-db-ja.com

C ++をサーバー側のWeb開発言語として使用できますか?

サーバー側の「スクリプト言語」としてC++を使用してWeb開発を始めたいのですが。私のサーバーインフラストラクチャは* nixベースであるため、AzureのC++でWeb開発を行うことは適用できず、C++/CLI ASP.NETも適用できません。

レガシーCGIアプリケーションとは別に、C++を使用してWeb開発を行うことはできますか?

34
Scott Davies

もちろんです。

Wtcppcms[〜#〜] csp [〜#〜] など、それらを開発するためのフレームワークもいくつかあります。 FastCGIのメインライン実装はCであり、C++を含む いくつかの言語 を直接サポートしています。

文字列を解析できるプログラミング言語であれば、CGIまたはサーブレットで使用できます。 Cライブラリとのバインディングを実装できる任意の言語を使用して、ISAPIまたはApache互換サーバー用のモジュールを開発することもできます。

C++では特に簡単ではありません。優れたテンプレートエンジンはほとんどありませんが、それは可能です。

もちろん、これが良いアイデアかどうかという問題は、まったく別の問題です。 :)

注意事項:Amazon.com、eBay、Googleなどの主要なWebサイトでは、インフラストラクチャの一部にC++を使用しています。ただし、Googleは速度重視のシステムにC++のみを使用しており、Amazon.comは比較的最近になってLISPから切り替わったことを認識しています(これにより、上級スタッフの一部が怒りました:)。

Facebookは以前にC++にPHP=をコンパイルしましたが、彼らのHipHopコンパイラー(一部はC++で書かれています)は、バイトコード仮想マシンとして再構築されています。

56
greyfade

何故なの?

OkCupid 出会い系サイトはC++で作成されています。おそらく他の例があります。

Wt と呼ばれる、C++でWebアプリケーションを開発するためのQtにヒントを得たツールキットもあります。

18
Vitor Py

C++でWebアプリケーションを作成することを計画している場合、CGIとしてインターフェースするのはまったく無駄です。

私の提案は [〜#〜] asio [〜#〜] (非同期I/O)を使用して非同期でビルドすることです。これで、非常に高速なWebサービスを構築できます(最適な効果を得るには、 nginxをリバースプロキシとして と静的サーバーを組み合わせます)。これを Wt のようなテンプレートライブラリと組み合わせると、1台のサーバーから1秒あたり数万のリクエストを処理する準備が整います。

これが動的言語Webフレームワークの実用的な代替策であるかどうかは、別の問題です。

11
vartec

簡単に言うと、入力の読み取り、解釈可能な出力の書き込み、およびWebサーバーによる実行が可能であれば、何でもWebページの書き込みに使用できます。

技術的には、任意の言語をCGIスクリプトとして使用できます。

  1. サーバーが提示するすべての入力と環境を解釈します
  2. 既知のマークアップ言語(通常はhtml)での出力
  3. サーバーで実行できます

他の方法もあります。 Perlは、c/c ++コードのラッパーとして構築され、2つの間の解釈レイヤーとして機能します(これには、CとしてフラットコンパイルされたPerlモジュールは含まれません)。

9
Avatar_Squadron

最初はかなり一般的でした。1990年代後半に私が最初に取り組んだWebサイトは、C++で記述されたISAPI拡張機能であり、非常にうまく機能していました。

7
Steven A. Lowe

Microsoftも可能だと考えているようです。チェックアウト Casablanca これは、C++を使用するAzure用の新しいツールセットです(表示されます)。

カサブランカは、クラウドコンピューティングが表すソフトウェアアーキテクチャの急激な変化を利用したいC++開発者を最もよくサポートする方法を模索するプロジェクトです。

カサブランカで得られるものは次のとおりです。

  • HTTP、JSON、およびURIへの非同期C++バインディングを提供することにより、Windows Vista、Windows 7、およびWindows 8コンシューマープレビューのネイティブコードからRESTサービスにアクセスするためのサポート
  • Windows 8 MetroスタイルアプリでC++ HTTPクライアントサイドコードを作成するのに役立つVisual Studio拡張SDK
  • Visual Studio統合を含む、Azureのネイティブコードの書き込みのサポートREST
  • ファーストクラスのサービスとしてのプラットフォーム(PaaS)機能としてネイティブクライアントからAzure BLOBおよびキューストレージにアクセスするための便利なライブラリ
  • C++ 11機能に基づく非同期操作を作成するための一貫した強力なモデル
  • ErlangアクターベースのプログラミングモデルのC++実装
  • サンプルとドキュメントのセット
5
gbjbaanb

PHPすることができます 独自のC/C++拡張機能を記述 して、そのように優れたパフォーマンス上の利点を得ることができます。WebアプリケーションのCPUを非常に多く使用する部分がある場合、おそらくその処理を拡張機能にオフロードし、結果をPHPに返し、次にPHPがそれをブラウザに出力します。

他の人があまり考慮しないことは、特定のCPU処理をクライアント側にオフロードすることです。 JavaScript/jQuery。 Webサーバーがある場合、特定の機能(データ処理など)にCPUを集中的に使用する処理を行うには、3Ghz CPUが必要になることがあります。私の会社は、そのサーバーを稼働させ続けるために毎月そのサーバーにお金を払っています。そのCPU集中型タスクを同時に実行している100人の同時ユーザーの操作をスケールアップしたい場合は、複数のCPUとサーバーが必要になり、ビジネスのコストが増加する可能性があります。 CPUを集中的に使用するタスクをクライアント側にオフロードすると、Webサイトにアクセスする各ユーザーがデータに対して独自の処理を実行できるため、サーバーの機能を増やす必要がないため、コストを節約できます。

結局のところ、100以上のデスクトップ/タブレット/モバイルの処理能力を備えた処理能力を備えたサーバーは、どこかでデータセンターにあるサーバーよりもはるかに多くの電力を消費し、毎月ビジネスコストをかけて実行し続ける必要があります。場合によっては、サーバーが実行するすべてのことは、データベースからデータを取得し、コンテンツを提供し、データベースに戻す前にデータの前処理と後処理と検証を行うことです。明らかに、クライアント側のコードを過度にCPUに集中させないでください。これは、WebブラウザーUIをブロック/フリーズする可能性があります。サーバーにAJAXリクエストを発行し、データを取得してから処理します。クライアント側で非同期にデータを送信し、WebブラウザーのUIを完全に使用可能にします。

2
zuallauz

はい、使用できます。他の人はさまざまなアプローチに言及しています。ここに私自身のアプローチがあります。利点は、それが完全に移植可能で自己完結型であり、選択したすべてのライブラリがANSI Cにのみ依存していることです。設定には、LinuxカーネルとCコンパイラ(およびBusybox、bashなどの明らかなもの)(またはWindowsのみ)が必要です。とコンパイラ)、追加のライブラリは必要ありません。豪華な巨大なインストールは必要ありません。

結果は、Webサーバーと動的ページジェネレーターの両方である単一のプログラム( "Apache"と "php"の両方を置き換えます)であり、sqliteを介してデータベースにアクセスできます。

使用ライブラリ:

  • Mongoose-HTTPサーバー
  • Sqlite-SQLデータベース
  • MiniXML-動的なページ生成を容易にします。 JavascriptのようなcreateElement

この回答の残りは、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に移動します

完了:)

2
Hello World

いくつかの組み込みシステム(ルーター、プリンターなど)には、C++駆動のWebサーバーがいくつかあると思います。

特に、 libonion のようなHTTPサーバーライブラリを使用して、CまたはC++プログラムにWeb機能を追加したり、Webインターフェイスを備えた軽量サーバーを開発したりできます。

一部の人々は Ocsigen を使用して、OcamlでWebサーバーまたはHTTPインターフェイスをコーディングしています。すべてのWebがPHPであるとは限りません。そして FastCGI を使用すると、アプリケーションで動的なWeb処理を行うことができます。