服务器开发中不何或缺的要使用fastcgi,其使用方法如下:
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 ); }
#undef fprintf #define fprintf FCGI_fprintf #undef printf #define printf FCGI_printf
现实开发中,可能会出现各种问题,有时候的确需要打印出一些信息,这时候可以修改fcgi_stdio.h头文件,改成如下:
#undef _fprintf #define _fprintf FCGI_fprintf #undef _printf #define _printf FCGI_printf
fastcgi 的解析可以通过这个函数:
char *getenv(const char *name)
CONTENT_TYPE
CONTENT_TYPE | 得到请求类型 |
CONTENT_LENGTH | 正文段长度 |
QUERY_STRING | 请求字串 |
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
#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
void fcgi_net_duty::do_request() { while( FCGI_Accept() >= 0 ){ do_prev(); do_cast(); do_handle(); do_write(); do_finish(); } }
fcig_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__
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(); }
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)