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で行われる予定です。 開発をテストして支援したい人はいつでも歓迎します。

Source: https://habr.com/ru/post/J111587/


All Articles