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


34

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

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


33
もちろんそれは可能です、質問は次のとおりです。それは実用的ですか?
エドS.

stackoverflow.comでこの質問を参照してください。
ケビンクライン

24
必要に応じて、アセンブリをサーバー側の言語として使用できます。
Channel72

8
またはBrainf * ck ,.ソケットにリダイレクトされる場合も。
dan04

4
これにより、私が関与した最初のWebプロジェクトの恐ろしい思い出がよみがえります。CコードへのCGIゲートウェイ。私はそれについて考えるとき、まだ震えています!:-)
ブライアンノブラウチ

回答:


56

絶対に。

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

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

C ++では特に簡単なことではなく、優れたテンプレートエンジンはほとんどありませんが、実行することはできます。

もちろん、これが良いアイデアであるかどうかの問題は完全に別の問題です。:)

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

Facebookは以前、PHPをC ++にコンパイルしていましたが、HipHopコンパイラ(C ++で部分的に記述されています)は、バイトコード仮想マシンとしてリツールされました。


2
+1さまざまなフレームワークを引用します。追加する必要があるのは、(非常に)大きなWebアプリがc ++(およびその他の言語)で強化されていることです:amazon.com、google.com、現在はhiphopを介したfacebook.comなど
11年

7
@Klaim:それは一般的ですが、決して規則ではありません。Amazonのアーキテクチャは歴史的にLispベースであり、ごく最近になってC ++で書き直されました。Googleのアーキテクチャには、Java、Python、およびC ++とほぼ同じ頻度で使用される他のさまざまな理由が含まれます。現在、Facebookはヒップホップを使用しているのは、PHPがスケーリングしないことを発見したためです。:)
greyfade

4
私は同意しますが、元の質問のタイトルに直接答えるために、それらはまだC ++の使用のよく知られた例であることを意味しました。
クライム

1
@johannes Facebookのスケーリングの問題は、特に最適化されたPHPスクリプトのパフォーマンスが低いために、他の場合よりも1桁以上多くのサーバーを維持する必要があるという事実に起因しています。このような大規模なインフラストラクチャでは、線形スケーリングだけでは不十分です。しかし、「何も共有しない」アプローチはPHPに限定されないことを忘れないでください。CとC ++も同様にできます。
greyfade

1
@amar実のところ、その生のパフォーマンスを必要とするアプリの0.1%を除いて、ほとんど利益はありません。Webスタックが適切にサポートされていれば、他のほとんどの言語で1/3の時間でサービスを提供できます。銀行、ウェブ広告主などはすべて、C ++に頼らずに大規模なサービスを提供しています。Facebookでも。Twitter。スタックオーバーフロー。すべて高レベルの言語で実行します。ここに留まることはできますが、再び多数派になることはありません。おそらく今まで。
リグ

18

何故なの?

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

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


11
「なぜ」この種のことをよりサポートする言語を使用する方がはるかに簡単だからです。
エドS.

5
@Ed S.私とgreyfadeが指摘したように、C ++でWebアプリケーションを開発するためのフレームワークがあります。
Vitor Py

2
はい、しかし再び、それらはより一般的に使用されるフレームワークと同じくらい使いやすいですか?私は正直言って、私はウェブ開発者ではなく、一度も使用したことはありませんが、Ruby / Python / PHPのカウンターパートほど成熟していないか、広く使用されていないようです。
エドS.

3
@EdS .: RubyもPythonもWebフレームワークで開始しませんでした。実際、登場するのに10年かかりました。フレームワークは、問題Yに言語Xを使用したいという十分な人々の単なる結果です。C++でも同じことが起こります。それができなかった主な理由:C ++は管理されておらず、コンパイルに時間がかかり、一般的に入り口の障壁が高い。
back2dos

1
@ back2dos:どちらの言語もウェブを念頭に置いて開発されたと誰が言いましたか?私は確かにしませんでした。「サポート」という用語を使用しました。
エドS.

11

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

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

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


9

簡単な答えは、ANYTHINGを使用すると、入力の読み取り、解釈可能な出力の書き込み、およびWebサーバーによる実行が可能なWebページの書き込みに使用できます。

技術的には、どの言語でもCGIスクリプトとして使用できます:

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

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



5

マイクロソフトもできると考えているようです。C ++を使用したAzure向けの新しいツールセットであるCasablancaを確認してください。

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

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

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

2

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

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

結局のところ、100台以上のデスクトップ/タブレット/モバイルの集合的な力で処理を行っているため、サーバーがどこかにあるデータセンターに設置されているサーバーよりもはるかに強力で、毎月ビジネスコストがかかります。潜在的には、サーバーが行うことはすべて、データベースからデータを取得し、コンテンツを提供し、データベースに保存する前にデータの事前/事後処理と検証を行うことです。明らかに、WebブラウザーUIをブロック/フリーズする可能性のあるクライアント側のコードをCPUに過度に集中させないでください。サーバーへのAJAXリクエストを実行し、データを取得してから、クライアント側で非同期にデータを処理し、Webを残します。 -ブラウザUIは完全に使用可能です。


2

はい、使用できます。他の人はさまざまなアプローチに言及しています。ここに私自身のアプローチがあります。利点は、完全に移植可能で自己完結型であり、選択されたすべてのライブラリが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 zipから: 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.outlocalhost:8080/hello

完了:)



@Hey:このMongooseの代替案を指摘してくれてありがとう、私は常にコミュニティ主導のプロジェクトを好みます。徹底的にテストした後、おそらく回答でMongooseをCivetwebに置き換えます。
ハローワールド

0

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

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.