#include <cstdlib>
#include <fcgio.h>
#define REQMAX 5242880
#define BUFSIZE 65536
using namespace std;
//得到环境变量
string safeGetEnv(const char* name,FCGX_Request * request){
const char* ptr = FCGX_GetParam(name, request->envp);
if(ptr == NULL){
return "";
}else{
return string(ptr);
}
}
//取得输入
long gstdin(FCGX_Request *request,string &reqstr,string &ip,string &cookie){
long reqlength=-1,len=0,i;
//得到IP地址
ip = safeGetEnv("REMOTE_ADDR",request);
if(ip==""){
ip="0.0.0.0";
}
//得到cookie
cookie = safeGetEnv("HTTP_COOKIE",request);
//判断请求类型
string reqmtd=safeGetEnv("REQUEST_METHOD",request);
if(reqmtd=="POST"){
string reqlen = safeGetEnv("CONTENT_LENGTH",request);
char buffer[BUFSIZE+1];
if(reqlen!=""){
reqlength=strtoul(reqlen.c_str(), NULL, 10);
}
if(reqlength<=0){
return -1; //错误
}
if(reqlength>REQMAX+1024){
return -2; //请求忒长了
}
//读标准输入
while(len<reqlength){
cin.read(buffer,BUFSIZE);
i=cin.gcount();
if(i<=0){
return -1; //错误
}
len+=i;
reqstr.append(buffer,i);
}
}else{
reqstr=safeGetEnv("QUERY_STRING",request);
reqlength=reqstr.length();
}
return reqlength;
}
int main(int argc,char *argv[]){
FCGX_Request request;
FCGX_Init();
FCGX_InitRequest(&request, 0, 0);
while (FCGX_Accept_r(&request) == 0){
fcgi_streambuf cin_
fcgi_streambuf(request.in);
fcgi_streambuf cout_
fcgi_streambuf(request.out);
fcgi_streambuf cerr_
fcgi_streambuf(request.err);
cin.rdbuf(&cin_
fcgi_streambuf);
cout.rdbuf(&cout_
fcgi_streambuf);
cerr.rdbuf(&cerr_
fcgi_streambuf);
string reqstr="",ip="",cookie="";
long reqlen=gstdin(&request,reqstr,ip,cookie);
if(reqlen<0){
continue;
}
cout<<"Content-Type: text/plain\r\n\r\n";
cout<<"IP:["<<ip<<"]\n";
cout<<"Cookie:["<<cookie<<"]\n";
cout<<"REQUEST:\n"<<reqstr<<endl;
}
return 0;
}
fcgi作为客户端需要注意的几点
http://blog.csdn.net/cleanfield/article/details/6699952
fcgi作为中间层,需要与后端server通信进行数据处理,这里需要注意一下几点:
1.要做好超时处理,fcgi跟cgi不同,往往只有几个固定数量的进程,与server类似,因为如果一个fcgi进程挂住会导致整个fcgi逻辑层的处理能力下降N分之一(N为fcgi进程数)。这里的超时包括connect超时、send超时和recv超时
2.server对每一次fcgi请求都要有回包,在fcgi recv到回包后退出处理,关闭与server的连接
3.recv时要注意一定要recv到整个逻辑包(注意这里是整个逻辑包,即包头中标识的包头+包体的长度,收完这样一块buff才可以认为是recv完成)
4.注意mtu,1500,如果是通过poll来实现recv超时,一定要注意3中提到的recv全部逻辑意义上的完整包,因为对于大于mtu的包来说,肯定会大于一次发送,所以recv也必须大于一次
最新的socket库可以在http://download.csdn.net/source/3530843页面下载,希望对有这方面需求的同学们有所帮助
fcgi demo
fcgi作为中间层,需要与后端server通信进行数据处理,这里需要注意一下几点:
1.要做好超时处理,fcgi跟cgi不同,往往只有几个固定数量的进程,与server类似,因为如果一个fcgi进程挂住会导致整个fcgi逻辑层的处理能力下降N分之一(N为fcgi进程数)。这里的超时包括connect超时、send超时和recv超时
2.server对每一次fcgi请求都要有回包,在fcgi recv到回包后退出处理,关闭与server的连接
3.recv时要注意一定要recv到整个逻辑包(注意这里是整个逻辑包,即包头中标识的包头+包体的长度,收完这样一块buff才可以认为是recv完成)
4.注意mtu,1500,如果是通过poll来实现recv超时,一定要注意3中提到的recv全部逻辑意义上的完整包,因为对于大于mtu的包来说,肯定会大于一次发送,所以recv也必须大于一次
最新的socket库可以在http://download.csdn.net/source/3530843页面下载,希望对有这方面需求的同学们有所帮助
fcgi demo