サーバー側で「スクリプト言語」としてC ++を使用してWeb開発に参加したいと思います。私のサーバーインフラストラクチャは* nixベースであるため、AzureでのC ++でのWeb開発は適用できず、C ++ / CLI ASP.NETも適用できません。
レガシーCGIアプリケーションとは別に、C ++を使用してWeb開発を実行できますか?
,
が.
ソケットにリダイレクトされる場合も。
サーバー側で「スクリプト言語」としてC ++を使用してWeb開発に参加したいと思います。私のサーバーインフラストラクチャは* nixベースであるため、AzureでのC ++でのWeb開発は適用できず、C ++ / CLI ASP.NETも適用できません。
レガシーCGIアプリケーションとは別に、C ++を使用してWeb開発を実行できますか?
,
が.
ソケットにリダイレクトされる場合も。
回答:
絶対に。
Wt、cppcms、CSPなど、それらを開発するためのフレームワークもいくつかあります。FastCGIのメインライン実装はCであり、C ++を含む複数の言語を直接サポートします。
文字列を解析できる任意のプログラミング言語は、CGIまたはサーブレットで使用できます。Cライブラリとのバインディングを実装できる言語は、ISAPIまたはApache互換サーバー用のモジュールの開発にも使用できます。
C ++では特に簡単なことではなく、優れたテンプレートエンジンはほとんどありませんが、実行することはできます。
もちろん、これが良いアイデアであるかどうかの問題は完全に別の問題です。:)
注: Amazon.com、eBay、Googleなどの主要なWebサイトでは、インフラストラクチャの一部にC ++を使用しています。ただし、Googleは速度が重要なシステムにのみC ++を使用し、Amazon.comは比較的最近Lisp(上級スタッフの一部を怒らせた:)に切り替えたにすぎないことを認識してください。
Facebookは以前、PHPをC ++にコンパイルしていましたが、HipHopコンパイラ(C ++で部分的に記述されています)は、バイトコード仮想マシンとしてリツールされました。
何故なの?
OkCupid出会い系サイトは、C ++で作成されます。おそらく他の例もあります。
Wtと呼ばれるC ++でWebアプリケーションを開発するためのQtにヒントを得たツールキットもあります。
簡単な答えは、ANYTHINGを使用すると、入力の読み取り、解釈可能な出力の書き込み、およびWebサーバーによる実行が可能なWebページの書き込みに使用できます。
技術的には、どの言語でもCGIスクリプトとして使用できます:
他の方法もあります。Perlには、c / c ++コードのラッパーとしてビルドする機能があり、2つの間の解釈レイヤーとして機能します(これには、Cとしてコンパイルされたperlモジュールは含まれません)。
当初、それは非常に一般的でした-1990年代後半に私が最初に取り組んだWebサイトはC ++で記述されたISAPI拡張であり、非常にうまく機能しました。
マイクロソフトもできると考えているようです。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 ++実装
- サンプルとドキュメントのセット
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は完全に使用可能です。
はい、使用できます。他の人はさまざまなアプローチに言及しています。ここに私自身のアプローチがあります。利点は、完全に移植可能で自己完結型であり、選択されたすべてのライブラリがANSI Cのみに依存することです。セットアップには、LinuxカーネルとCコンパイラ(およびBusybox、bashなどの明らかなもの)(またはWindowsおよびコンパイラ)、追加のライブラリは必要ありません、派手な巨大なインストールはありません。
結果は、Webサーバーと動的ページジェネレーター(「apache」と「php」の両方を代用する)の両方である単一のプログラムになり、sqliteを介したデータベースアクセスも可能になります。
使用されるライブラリ:
createElement
この回答の残りは、Linuxの完全なセットアップガイドです。SQliteとMiniXMLはどちらもオプションですが、このガイドでは完全なインストールについて説明しています。sqliteまたはMiniXMLを無効にすることに関心がある場合は、不要な部分をコメント化するのはあなた次第です。
1. 3つのライブラリをダウンロードします
2.フォルダーを準備する
sqlite3.c , sqlite3.h
mongoose.c , mongoose.h
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
libmxml.a, mxml.h
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
完了:)