libscgiは、シンプルで高速なスクリプトのための効果的なソリューションです

多くの場合、非常に迅速に機能するシンプルで軽量なソリューションを実装する必要があります。 そして、AJAXテクノロジーの使用により、これはさらに重要になりました。 オートコンプリートスクリプト、特定の検索スクリプト、ディレクトリから出力される情報のようになります。 以前に使用されたcgiスクリプト。 重い負荷の下では、それらはあまり効果的ではなく、fcgiおよびscgiプロトコルが開発されました。 scgiサーバーのパフォーマンスは非常に高く(1500 bps /秒以上)、メモリは600Kしか消費しないことに注意してください。



Simple Common Gateway Interface (SCGI)は、アプリケーションとWeb(http)サーバーとの相互作用のためのプロトコルです。 最新のWEBサーバー(Apache / nginx / lighttpd)には組み込みのscgiサポートがあります。 以下は、単純なライブラリ(scgiサーバー)の使用に関する簡単な説明です。



ソースはこちら



プロトコルの説明。


クライアントは、8ビットバイトの転送を可能にするストリーム転送プロトコルを使用してSCGIサーバーに接続します。 リクエストは、いくつかのヘッダーとリクエスト本文(POST DATA)で構成されますリクエストデータの転送形式には、次のテンプレートがあります: [len header]: \r\n

[header parm name] \0 [header parm value] \0 \r\n

[header parm name] \0 [header parm value] \0 \r\n

...

,\r\n

[POST DATA]




[len header]: \r\n

[header parm name] \0 [header parm value] \0 \r\n

[header parm name] \0 [header parm value] \0 \r\n

...

,\r\n

[POST DATA]








最初のヘッダーの名前は「CONTENT_LENGTH」である必要があり、その値にはメッセージ本文の長さ(10進数)を示す必要があります。 ヘッダー「CONTENT_LENGTH」は、その値が0(すべてのGET要求)であっても、常に送信する必要があります。 ヘッダーとリクエスト本文の間は、コンマと改行である必要があります。 ヘッダー(POST / PUTデータ)がヘッダーに送信され、その長さは見出し "CONTENT_LENGTH"によって決定される必要があります。



Nginxのセットアップ

マニュアルでは、各WEBサーバーに1つまたは別のモジュールの接続方法に関する指示が添付されている必要があります。 scginサーバーをnginxで構成しました。

特定の場所、ポート8080の構成例。

location /dictionary {

scgi_pass localhost:8080;

include scgi_params;

}






内部デバイスscgiサーバーとその使用


サーバーはlibeventに基づいて実装されます。 使用される各URL(DOCUMENT_URIヘッダー)には独自のハンドラーがあります。

scgi.addHandler("/post", reinterpret_cast<IScgiHandler *>(new Handler1()));







各カスタムハンドラーは、IScgiHandlerクラス継承のrun()メソッドで定義する必要があります。

次のパラメーターがこのメソッドに渡されます。

map< string,string > * parms - ,

char * buffUot - .







受信したすべてのPOSTデータは、キー「POST_DATA」とともにパラメーターに保存されます。

入力パラメーターへのアクセスは、protectedメソッドを使用して簡素化されます。getParam(string parnName、map <string、string> * parms);



サンプルハンドラーコードを考えます。



  1. class Handler1 : public IScgiHandler { void run ( map < string,string > * parms, char * buffUot ) { string parm = getParam ( "REQUEST_METHOD" ,parms ) ; // POST if ( parm == "POST" ) { // WEB-client POST strcpy ( buffUot, getParam ( "POST_DATA" ,parms ) . c_str ( ) ) ; return ; } // WEB-client QUERY_STRING strcpy ( buffUot, getParam ( "QUERY_STRING" ,parms ) . c_str ( ) ) ; } } ;



  2. class Handler1 : public IScgiHandler { void run ( map < string,string > * parms, char * buffUot ) { string parm = getParam ( "REQUEST_METHOD" ,parms ) ; // POST if ( parm == "POST" ) { // WEB-client POST strcpy ( buffUot, getParam ( "POST_DATA" ,parms ) . c_str ( ) ) ; return ; } // WEB-client QUERY_STRING strcpy ( buffUot, getParam ( "QUERY_STRING" ,parms ) . c_str ( ) ) ; } } ;



  3. class Handler1 : public IScgiHandler { void run ( map < string,string > * parms, char * buffUot ) { string parm = getParam ( "REQUEST_METHOD" ,parms ) ; // POST if ( parm == "POST" ) { // WEB-client POST strcpy ( buffUot, getParam ( "POST_DATA" ,parms ) . c_str ( ) ) ; return ; } // WEB-client QUERY_STRING strcpy ( buffUot, getParam ( "QUERY_STRING" ,parms ) . c_str ( ) ) ; } } ;



  4. class Handler1 : public IScgiHandler { void run ( map < string,string > * parms, char * buffUot ) { string parm = getParam ( "REQUEST_METHOD" ,parms ) ; // POST if ( parm == "POST" ) { // WEB-client POST strcpy ( buffUot, getParam ( "POST_DATA" ,parms ) . c_str ( ) ) ; return ; } // WEB-client QUERY_STRING strcpy ( buffUot, getParam ( "QUERY_STRING" ,parms ) . c_str ( ) ) ; } } ;



  5. class Handler1 : public IScgiHandler { void run ( map < string,string > * parms, char * buffUot ) { string parm = getParam ( "REQUEST_METHOD" ,parms ) ; // POST if ( parm == "POST" ) { // WEB-client POST strcpy ( buffUot, getParam ( "POST_DATA" ,parms ) . c_str ( ) ) ; return ; } // WEB-client QUERY_STRING strcpy ( buffUot, getParam ( "QUERY_STRING" ,parms ) . c_str ( ) ) ; } } ;



  6. class Handler1 : public IScgiHandler { void run ( map < string,string > * parms, char * buffUot ) { string parm = getParam ( "REQUEST_METHOD" ,parms ) ; // POST if ( parm == "POST" ) { // WEB-client POST strcpy ( buffUot, getParam ( "POST_DATA" ,parms ) . c_str ( ) ) ; return ; } // WEB-client QUERY_STRING strcpy ( buffUot, getParam ( "QUERY_STRING" ,parms ) . c_str ( ) ) ; } } ;



  7. class Handler1 : public IScgiHandler { void run ( map < string,string > * parms, char * buffUot ) { string parm = getParam ( "REQUEST_METHOD" ,parms ) ; // POST if ( parm == "POST" ) { // WEB-client POST strcpy ( buffUot, getParam ( "POST_DATA" ,parms ) . c_str ( ) ) ; return ; } // WEB-client QUERY_STRING strcpy ( buffUot, getParam ( "QUERY_STRING" ,parms ) . c_str ( ) ) ; } } ;



  8. class Handler1 : public IScgiHandler { void run ( map < string,string > * parms, char * buffUot ) { string parm = getParam ( "REQUEST_METHOD" ,parms ) ; // POST if ( parm == "POST" ) { // WEB-client POST strcpy ( buffUot, getParam ( "POST_DATA" ,parms ) . c_str ( ) ) ; return ; } // WEB-client QUERY_STRING strcpy ( buffUot, getParam ( "QUERY_STRING" ,parms ) . c_str ( ) ) ; } } ;



  9. class Handler1 : public IScgiHandler { void run ( map < string,string > * parms, char * buffUot ) { string parm = getParam ( "REQUEST_METHOD" ,parms ) ; // POST if ( parm == "POST" ) { // WEB-client POST strcpy ( buffUot, getParam ( "POST_DATA" ,parms ) . c_str ( ) ) ; return ; } // WEB-client QUERY_STRING strcpy ( buffUot, getParam ( "QUERY_STRING" ,parms ) . c_str ( ) ) ; } } ;



  10. class Handler1 : public IScgiHandler { void run ( map < string,string > * parms, char * buffUot ) { string parm = getParam ( "REQUEST_METHOD" ,parms ) ; // POST if ( parm == "POST" ) { // WEB-client POST strcpy ( buffUot, getParam ( "POST_DATA" ,parms ) . c_str ( ) ) ; return ; } // WEB-client QUERY_STRING strcpy ( buffUot, getParam ( "QUERY_STRING" ,parms ) . c_str ( ) ) ; } } ;



  11. class Handler1 : public IScgiHandler { void run ( map < string,string > * parms, char * buffUot ) { string parm = getParam ( "REQUEST_METHOD" ,parms ) ; // POST if ( parm == "POST" ) { // WEB-client POST strcpy ( buffUot, getParam ( "POST_DATA" ,parms ) . c_str ( ) ) ; return ; } // WEB-client QUERY_STRING strcpy ( buffUot, getParam ( "QUERY_STRING" ,parms ) . c_str ( ) ) ; } } ;



  12. class Handler1 : public IScgiHandler { void run ( map < string,string > * parms, char * buffUot ) { string parm = getParam ( "REQUEST_METHOD" ,parms ) ; // POST if ( parm == "POST" ) { // WEB-client POST strcpy ( buffUot, getParam ( "POST_DATA" ,parms ) . c_str ( ) ) ; return ; } // WEB-client QUERY_STRING strcpy ( buffUot, getParam ( "QUERY_STRING" ,parms ) . c_str ( ) ) ; } } ;



  13. class Handler1 : public IScgiHandler { void run ( map < string,string > * parms, char * buffUot ) { string parm = getParam ( "REQUEST_METHOD" ,parms ) ; // POST if ( parm == "POST" ) { // WEB-client POST strcpy ( buffUot, getParam ( "POST_DATA" ,parms ) . c_str ( ) ) ; return ; } // WEB-client QUERY_STRING strcpy ( buffUot, getParam ( "QUERY_STRING" ,parms ) . c_str ( ) ) ; } } ;







サーバーの起動は非常に簡単です。

  1. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  2. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  3. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  4. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  5. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  6. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  7. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  8. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  9. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  10. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  11. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  12. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  13. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  14. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  15. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  16. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  17. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  18. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  19. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;



  20. // scgiServer scgi ; // pid_t pid ; if ( ( pid = scgi. demonize ( ) ) < 1 ) { if ( pid == - 1 ) { cerr << "demonize error \n " ; return 1 ; } return 0 ; } // if ( scgi. init ( "127.0.0.1" , 8080 ) ) { cerr << "server stopped \n " ; return 1 ; } // scgi. addHandler ( "/post" , reinterpret_cast < IScgiHandler * > ( new Handler1 ( ) ) ) ; scgi. addHandler ( "/xxx" , reinterpret_cast < IScgiHandler * > ( new Handler2 ( ) ) ) ; scgi. run ( ) ;







設置


ライブラリは静的として実装されます。

make lib-ライブラリのコンパイル

makeはサンプルファイルをコンパイルします



アプリケーションのコンパイル:

cp libscgi.a / usr / local / lib

g ++ example.cpp -o scgi_server -Wall -g -L -L / usr / local / lib -levent -lscgi



制限事項:


POSTデータと応答の長さは2K以下にする必要があります。 この制限は、対応する値を#define BUFFSIZE定数に設定し、ライブラリを再構築することで変更できます。 これで私の仕事には十分です。

このライブラリは実験的なものであり、欠陥や潜在的な欠陥があります。 建設的な批判は大歓迎です。 TODOで行われる予定です。 開発をテストして支援したい人はいつでも歓迎します。



All Articles