程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> fastcgi 的使用與封裝

fastcgi 的使用與封裝

編輯:C++入門知識

服務器開發中不何或缺的要使用fastcgi,其使用方法如下:


[cpp]
while( FCGI_Accept() >= 0 ){ 
                printf( "Content-type: text/plain \r\n" 
                "Content-Length: %d\r\n" 
                "Connection: close\r\n\r\n%s\r\n", strlen( buffer ), buffer ); 
        } 

while( FCGI_Accept() >= 0 ){
                printf( "Content-type: text/plain \r\n"
                "Content-Length: %d\r\n"
                "Connection: close\r\n\r\n%s\r\n", strlen( buffer ), buffer );
        }

 


facgcgi 頭文件有如下宏:


[cpp] 
#undef  fprintf  
#define fprintf  FCGI_fprintf  
#undef  printf  
#define printf   FCGI_printf 

#undef  fprintf
#define fprintf  FCGI_fprintf
#undef  printf
#define printf   FCGI_printf
可以看出,已經對printf函數進行了宏轉向,在程序裡的printf 不再是標准輸出了。這樣就有一個問題,如果想調試打印信息到stdout中,就不行了。

現實開發中,可能會出現各種問題,有時候的確需要打印出一些信息,這時候可以修改fcgi_stdio.h頭文件,改成如下:


[cpp]
#undef  _fprintf  
#define _fprintf  FCGI_fprintf  
#undef  _printf  
#define _printf   FCGI_printf 

#undef  _fprintf
#define _fprintf  FCGI_fprintf
#undef  _printf
#define _printf   FCGI_printf
在程序中的相應地方也要換成相應的宏。

 


fastcgi 的解析可以通過這個函數:


[cpp] 
char *getenv(const char *name)  

char *getenv(const char *name)
有如下幾類參數:


CONTENT_TYPE

CONTENT_TYPE 得到請求類型
CONTENT_LENGTH 正文段長度
QUERY_STRING 請求字串

以如下一段HTTP請求報文為例:


[cpp] 
GET /s?ie=utf-8&bs=%E8%BF%99%E6%98%AF&f=8&rsv_bp=1&rsv_spt=3&wd=%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%BC%80%E5%8F%91&rsv_sug3=11&rsv_sug=0&rsv_sug4=609&rsv_sug1=2&inputT=32681 HTTP/1.1 
Host: www.baidu.com 
Connection: keep-alive 
Content-Type: text/html;charset=utf-8 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31 
Referer: http://www.baidu.com/s?wd=%E8%BF%99%E6%98%AF&rsv_bp=0&ch=&tn=baidu&bar=&rsv_spt=3&ie=utf-8&rsv_sug3=4&rsv_sug=0&rsv_sug4=240&rsv_sug1=3&inputT=2835  
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: zh-CN,zh;q=0.8 
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3 
Cookie: BAIDUID=A83324E58AE26486E46FC49ED127891B:FG=1; BDSVRTM=163; H_PS_PSSID=1439_2448_2454_2256_1788_2249; WWW_ST=1369271667063 

GET /s?ie=utf-8&bs=%E8%BF%99%E6%98%AF&f=8&rsv_bp=1&rsv_spt=3&wd=%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%BC%80%E5%8F%91&rsv_sug3=11&rsv_sug=0&rsv_sug4=609&rsv_sug1=2&inputT=32681 HTTP/1.1
Host: www.baidu.com
Connection: keep-alive
Content-Type: text/html;charset=utf-8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
Referer: http://www.baidu.com/s?wd=%E8%BF%99%E6%98%AF&rsv_bp=0&ch=&tn=baidu&bar=&rsv_spt=3&ie=utf-8&rsv_sug3=4&rsv_sug=0&rsv_sug4=240&rsv_sug1=3&inputT=2835
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
Cookie: BAIDUID=A83324E58AE26486E46FC49ED127891B:FG=1; BDSVRTM=163; H_PS_PSSID=1439_2448_2454_2256_1788_2249; WWW_ST=1369271667063

CONTENT_TYPE 對應第5行,QUERY_STRING 對應第一行。

 

 

fastcgi 不是面向對象的,所有的任務都是在主循環內完成,包括解析,處理,響應。

在實際的開發中,為了提高效率,開發成員不用關心底層,我將其封裝成一個類:fcgi_net_duty


[cpp]
#ifndef __FCGI_NET_H__  
#define __FCGI_NET_H__  
 
#define FCGI_NET_OK           0  
#define FCGI_NET_ERROR        1  
#define FCGI_NET_PARAM_ERROR  2  
 
enum fcgi_net_type 

        FCGI_NET_TEXT = 0, 
        FCGI_NET_APP_STREAM, 
        FCGI_NET_IMAGE, 
}; 
 
class fcgi_net_duty 

public: 
        fcgi_net_duty(); 
        ~fcgi_net_duty(); 
 
        void do_request(); 
 
protected: 
        void  do_prev(); 
        void  do_cast(); 
        virtual void  do_handle(); 
        void  do_write(); 
        void  do_finish(); 
 
        int get_req_int( const char* param, int *value );         
        int get_req_ll( const char* param, long long *value ); 
        int get_req_str( const char* param, const char **value ); 
 
        int get_cookie_int( const char* param, int *value ); 
        int get_cookie_ll( const char* param, long long *value ); 
        int get_cookie_str( const char* param, const char **value ); 
 
 
private: 
        std::map< const char*, const char* > m_req; 
        std::map< const char*, const char* > m_cookie; 
 
        int rtn;         
        int content_type; 
        int content_length; 
        char* content_buf; 
 
}; 

#ifndef __FCGI_NET_H__
#define __FCGI_NET_H__

#define FCGI_NET_OK           0
#define FCGI_NET_ERROR        1
#define FCGI_NET_PARAM_ERROR  2

enum fcgi_net_type
{
        FCGI_NET_TEXT = 0,
        FCGI_NET_APP_STREAM,
        FCGI_NET_IMAGE,
};

class fcgi_net_duty
{
public:
        fcgi_net_duty();
        ~fcgi_net_duty();

        void do_request();

protected:
        void  do_prev();
        void  do_cast();
        virtual void  do_handle();
        void  do_write();
        void  do_finish();

        int get_req_int( const char* param, int *value );       
        int get_req_ll( const char* param, long long *value );
        int get_req_str( const char* param, const char **value );

        int get_cookie_int( const char* param, int *value );
        int get_cookie_ll( const char* param, long long *value );
        int get_cookie_str( const char* param, const char **value );


private:
        std::map< const char*, const char* > m_req;
        std::map< const char*, const char* > m_cookie;

        int rtn;       
        int content_type;
        int content_length;
        char* content_buf;

};

 

 

 

主循環放在do_request 函數裡

fcgi_net_duty.cpp


[cpp]
void fcgi_net_duty::do_request() 

        while( FCGI_Accept() >= 0 ){ 
                do_prev(); 
                do_cast(); 
                do_handle(); 
                do_write(); 
                do_finish(); 
        } 

void fcgi_net_duty::do_request()
{
        while( FCGI_Accept() >= 0 ){
                do_prev();
                do_cast();
                do_handle();
                do_write();
                do_finish();
        }
}

子類只需要關心相應的業務,每個業務可以用一個子類完成,如現有三個業務:busi1, busi2, busi3,我們以其中一個為例:

fcig_busi1.h


[cpp] 
#ifndef __FCGI_BUSI1_H__  
#define __FCGI_BUSI1_H__  
 
class fcgi_busi1 : public fcgi_net_duty 

public:  
        fcgi_busi1(); 
        ~fcgi_busi1(); 
 
        void do_handle(); 
 
}; 
 
 
#endif //__FCGI_BUSI1_H__ 

#ifndef __FCGI_BUSI1_H__
#define __FCGI_BUSI1_H__

class fcgi_busi1 : public fcgi_net_duty
{
public:
        fcgi_busi1();
        ~fcgi_busi1();

        void do_handle();

};


#endif //__FCGI_BUSI1_H__

 

fcgi_busi1.cpp
[cpp] 
void fcgi_busi1::do_handle() 

        const char* busi1; 
        int flag; 
 
        rtn = FCGI_NET_ERROR; 
 
        flag = get_req_str( "busi1", &busi1 ); 
        if( flag ){ 
                rtn = FCGI_NET_PARAM_ERROR; 
                return; 
        } 
 
        sprintf( content_buf, "%s","your busi is ok" ); 
        rtn = FCGI_NET_OK; 
 

 
int main() 

        fcgi_busi1 busi1; 
        busi1.do_request(); 

void fcgi_busi1::do_handle()
{
        const char* busi1;
        int flag;

        rtn = FCGI_NET_ERROR;

        flag = get_req_str( "busi1", &busi1 );
        if( flag ){
                rtn = FCGI_NET_PARAM_ERROR;
                return;
        }

        sprintf( content_buf, "%s","your busi is ok" );
        rtn = FCGI_NET_OK;

}

int main()
{
        fcgi_busi1 busi1;
        busi1.do_request();
}

相應的makefile:

[cpp]
INC=-I./  
LIB=-L/usr/lib64 -lfcgi 
 
CPPFLAGS=-g -w $(INC) 
CC=g++ 
 
BUSI1=./build/busi1 
BUSI2=./build/busi2 
BUSI3=./build/busi3 
 
all: $(BUSI1) $(BUSI2) $(BUSI3) 
 
$(BUSI1): ./fcgi_net_duty.o ./fcgi_busi1.o 
        $(CC) -O $@ $^ $(LIB) 
 
$(BUSI2): ./fcgi_net_duty.o ./fcgi_busi2.o 
        $(CC) -O $@ $^ $(LIB) 
 
$(BUSI3): ./fcgi_net_duty.o ./fcgi_busi3.o 
        $(CC) -O $@ $^ $(LIB) 

INC=-I./
LIB=-L/usr/lib64 -lfcgi

CPPFLAGS=-g -w $(INC)
CC=g++

BUSI1=./build/busi1
BUSI2=./build/busi2
BUSI3=./build/busi3

all: $(BUSI1) $(BUSI2) $(BUSI3)

$(BUSI1): ./fcgi_net_duty.o ./fcgi_busi1.o
        $(CC) -O $@ $^ $(LIB)

$(BUSI2): ./fcgi_net_duty.o ./fcgi_busi2.o
        $(CC) -O $@ $^ $(LIB)

$(BUSI3): ./fcgi_net_duty.o ./fcgi_busi3.o
        $(CC) -O $@ $^ $(LIB)
OK,現在一個輕型的fastcgi開發框架就搭建起來了,現實開發中,可以讓一個成員開發網絡處理,其他人專門做相應的業務處理,可以達到事半功倍的處理,我的理念就是讓專業的人做專業的事,這樣大家在專業技能上有更好的提升。

 


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved