Manage SPAWN-FCGI program management and FASTCGI library libfcgi unified package

Integrate and encapsulate the spawn-fcgi process management program with the libfcgi c++ library, so that the library can self-manage program start and stop and fcgi functions, The output is in json format and supports post and get methods.

如输入:http://192.168.1.123/PaymentRecords.cgi/?BillingCycle=201708&DestinatiosAttr=2
使用进程或线程函数读会得到信息:strjson=”{BillingCycle:201708 , DestinatiosAttr:2}”
readFcgi(string &strjson, unsigned int wait_seconds = 0);
bool readThreadFcgi(string &strjson, unsigned int wait_seconds = 0);
The above read can also support timeout, that is, timeout Stop blocking after not receiving the request. After processing the business, you can spell it into json format and write it back with the corresponding writeXXX function.
In addition to the above, you can also use the runXXX function to pass in the business function pointer, and the function will process the request in a loop, but this type of function does not support timeout.

SpawnFcgi.h:

/*** @file SpawnFcgi.h* @brief SpawnFcgi lib* @author wangcc3* @date 2017-8-17* @version 001* @copyright Copyright (c) 2017, AsiaInfo(FzOcs)*/#ifndef _SPAWNFCGI_H_#define _SPAWNFCGI_H_#include #include #include #include #include #include #include #include #include #include #include #include "fcgi_stdio.h"#include "fcgi_config.h"#include "fcgiapp.h"#include namespace BM35{using std::string;using std::map;using std::make_pair;#define FCGI_MAX_THREAD_NUMS 5#define gettid( ) syscall(__NR_gettid)typedef void (*business_fn)(string &,string &);class SpawnFcgi (public: SpawnFcgi(); ~SpawnFcgi(); bool initFcgi(unsigned short port = 9000, bool flag = true); bool readFcgi (string &strjson, unsigned int wait_seconds = 0); bool writeFcgi(string &strjson); bo ol runFcgi(business_fn func); bool setThreadInfo(); bool readThreadFcgi(string &strjson, unsigned int wait_seconds = 0); bool writeThreadFcgi(string &strjson); bool runThreadFcgi(business_fn func); string getErrorInfo();private: int _sockFD; static com } // BM35#endif // _SPAWNFCGI_H_

SpawnFcgi.cpp:

/*** @file SpawnFcgi.cpp* @brief SpawnFcgi lib* @author wangcc3* @date 2017-8-17* @version 001* @copyright Copyright (c) 2017,AsiaInfo (FzOcs)*/#include "SpawnFcgi.h"namespace BM35{const int SpawnFcgi::_stdinFD = 0;SpawnFcgi::SpawnFcgi() {_sockFD = -1; _errStr = "no error"; _requestCursor = 0;}SpawnFcgi: :~Spaw nFcgi() {}bool SpawnFcgi::initFcgi(unsigned short port, bool flag) {int optval = 1; int max_fd = 0; int i = 0; struct sockaddr_in addr; addr.sin_family=AF_INET; addr.sin_port=htons( port); addr.sin_addr.s_addr=htonl(INADDR_ANY); if (-1 == (_sockFD = socket(AF_INET, SOCK_STREAM, 0))) {char cTmp[256] = {0 }; sprintf(cTmp,"create socket failed! errno=%s",strerror(errno)); _errStr = cTmp; return false;} if (-1 == setsockopt(_sockFD, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))) {char cTmp[256 ] = {0 }; sprintf(cTmp,"set reuseaddr failed! errno=%s",strerror(errno)); _errStr = cTmp; return false;} if(-1 == bind(_sockFD, (struct sockaddr*) &addr,sizeof(addr))) {char cTmp[256] = {0 }; sprintf(cTmp,"bind socket failed! errno=%s",strerror(errno)); _errStr = cTmp; return false;} if ( -1 == listen(_sockFD, 1024)) {char cTmp[256] = {0 }; sprintf(cTmp,"set listen failed! errno=%s",strerror(errno)); _errStr = cTmp; return false;} if(_sockFD != _stdinFD) {close( _stdinFD); dup2(_sockFD, _stdinFD); close(_sockFD);} max_fd = open("/dev/null", O_RDWR); if (-1 != max_fd) {if (max_fd != STDOUT_FILENO) dup2(max_fd, STDOUT_FILENO); if (max_fd != STDERR_FILENO) dup2(max_fd, STDERR_FILENO); if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO) close(max_fd);} else {_erout/Strder to redirect to "couldn't '/dev/null'"; return false;} if(flag) {for (i = 3; i = 0) {char *method = FCGX_GetParam("REQUEST_METHOD", _the_request.envp); if(method && strcmp(method,"POST") == 0) {contentLength = FCGX_GetParam("CONTENT_LENGTH", _the_request.envp) ; if (contentLength != NULL) {len = strtol(contentLength, &contentLength, 10); if (*contentLength) {_errStr ="can't parser CONTENT_LENGTH"; return false;} if (len> 0) {int i, ch; for (i = 0; i = 0) {printf("Content-type: application/json\r\n\r\n" ); method= getenv("REQUEST_METHOD"); if(method && strcmp(method,"POST") == 0) {contentLength = getenv("CONTENT_LENGTH"); if (contentLength != NULL) {len = strtol(contentLength, &contentLength, 10 ); if (*contentLength) {_errStr ="can't parser CONTENT_LENGTH"; return false;} if (len> 0) {int i, ch; for (i = 0; i = FCGI_MAX_THREAD_NUMS) {_errStr ="have achieve max thread nums"; pthread_mutex_unlock(&set_mutex); return false;} _requestMap.insert(make_pair(gettid(), _requestCursor)); FCGX_InitRequest(&_request[_requestCursor], 0, 0); _requestCurs; return true;}bool SpawnFcgi::readThreadFcgi(string &strjson, unsigned int wait_seconds) {int rc; char *method = NULL; char *contentLength = NULL; char contentInfo[256] = {0 }; char *queryString = NULL; int len = 0; string inJson; int cursor =_requestMap[gettid()]; FCGX_Finish_r(&_request[cursor]); static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&accept_secondrTimeOut); if(!fcgiTime out"; pthread_mutex_unlock(&accept_mutex); return false;} rc = FCGX_Accept_r(&_request[cursor]); pthread_mutex_unlock(&accept_mutex); if (rc <0) {char cTmp[256] = {0 }; sprintf(cTmp,"accep t failed! errno=%d", rc); _errStr = cTmp; return false;} method = FCGX_GetParam("REQUEST_METHOD", _request[cursor].envp); if(method && strcmp(method,"POST") == 0) {contentLength = FCGX_GetParam("CONTENT_LENGTH", _request[cursor].envp); if (contentLength != NULL) {len = strtol(contentLength, &contentLength, 10); if (*contentLength) {_errStr ="can't parser CONTENT_LENGTH"; return false;} if (len> 0) {int i, ch; for (i = 0; i  0) {int i, ch; for (i = 0; i  1) strjson = strjson.substr(0, strjson.length( )-1); strjson = strjson + "}"; return true;}bool SpawnFcgi::fcgiTimeOut(unsigned int wait_seconds) {if (wait_seconds> 0) {int ret = 0; fd_set accept_fdset; struct timeval timeout; FD_ZERO (&accept_fdset ); FD_SET (_stdinFD, &accept_fdset ); timeout.tv_sec = wait_seconds; timeout.tv_usec = 0; do {ret = select( _stdinFD + 1, &accept_fdset, NULL, NULL, &timeout );} while (ret <0 && errno == EINTR ); if (ret == -1) return false; else if (ret == 0 ) {return false;}} return true;}string SpawnFcgi::getErrorInfo() {return _errStr;}}


Example program TestExample.cpp:

 #include "SpawnFcgi.h"#include #include /***nginx new configuration: * location ~ \.cgi$ {* fastcgi_pass 127.0.0.1:9000;* fastcgi_index index.cgi; * fastcgi_param SCRIPT_FILENAME fcgi$fastcgi_script_name;* include fastcgi_params;* }** Test tool: * Fiddler** Use: * Start nginx reverse proxy or tomcat and other support cgi server, run the compiled testFcgi program, *Fiddler tool simulates post and get Request**/using namespace std;using namespace BM35;void myfunc(string & inJson,string & outJson) {char tmp[64] = {0 }; pid_t pid = getpid(); s printf(tmp, "{\"pid\":\"%d\",", pid); outJson =tmp + inJson + "}";}void myfuncT(string & inJson,string & outJson) {char tmp[ 64] = {0 }; pthread_t tid= pthread_self(); sprintf(tmp, "{\"tid\":\"%d\",", tid); outJson =tmp + inJson + "}";}void * routine(void * arg) {SpawnFcgi * tmp =(SpawnFcgi *)arg; tmp->runThreadFcgi(myfuncT); return NULL;}void * routine1(void * arg) {SpawnFcgi * tmp =(SpawnFcgi *)arg; tmp ->setThreadInfo(); string info; while(tmp->readThreadFcgi(info)) {tmp->writeThreadFcgi(info);} return NULL;}int main() {SpawnFcgi * fcgi = new SpawnFcgi();#if defined (OneProcess) //Single process if(!fcgi->initFcgi(9000)) printf("init failed"); string info; while(fcgi->readFcgi(info)) {fcgi->writeFcgi(info); }# elif defined (multProcess1) // single process or multiple processes pid_t pid; if(!fcgi->initFcgi(9000)) printf("init failed"); pid = fork(); if(pid == 0) {string info ; while(fcgi->readFcgi(info)) { fcgi->writeFcgi(info);}} else if(pid> 0){ string info; while(fcgi->readFcgi(info)) {fcgi->writeFcgi(info);}} else {printf("fork error" ); }#elif defined (multProcess2) // single process or multiple process pid_t pid; if(!fcgi->initFcgi(9000)) printf("init failed"); pid = fork(); if(pid == 0 ) {fcgi->runFcgi(myfunc);} else if(pid> 0){ fcgi->runFcgi(myfunc);} else {printf("fork error"); }#elif defined (multProcessThread1) // Multi-threaded pid_t pid; if(!fcgi->initFcgi(9000)) printf("init failed"); pid = fork(); if(pid == 0) {// child process thread pthread_t threads[2]; for(int i = 0; i <2;i++) {pthread_create(&threads[i], NULL, routine, fcgi);} for(int i = 0; i <2; i++) {//If you use pthread_detach(pthread_self()) , Don’t wait anymore. pthread_join(threads[i], NULL); //Prevent zombie threads and wait}} else if(pid> 0){ // parent process thread pthread_t thr eads[3]; for(int i = 0; i <3;i++) {pthread_create(&threads[i], NULL, routine, fcgi);} for(int i = 0; i <3; i++) {// If you use pthread_detach(pthread_self()), you don’t need to wait. pthread_join(threads[i], NULL); //Prevent zombie threads and wait}} else {printf("fork error"); }#elif defined (multProcessThread2) // Multi-threaded pid_t pid; if(!fcgi->initFcgi(9000)) printf("init failed"); pid = fork(); if(pid == 0) {// Child process thread pthread_t threads[2] ; for(int i = 0; i <2;i++) {pthread_create(&threads[i], NULL, routine1, fcgi);} for(int i = 0; i <2; i++) {//If you use pthread_detach( pthread_self()), no need to wait pthread_join(threads[i], NULL); //prevent zombie threads, wait}} else if(pid> 0){ // parent process thread pthread_t threads[3]; for( int i = 0; i <3;i++) {pthread_create(&threads[i], NULL, routine1, fcgi);} for(int i = 0; i <3; i++) {//If you use pthread_d etach(pthread_self()), no need to wait for pthread_join(threads[i], NULL); //Prevent zombie threads, wait}} else {printf("fork error"); }#elif defined (timeOutTest) // Timeout test if(!fcgi->initFcgi(9000)) printf("init failed"); string info; /*thread fcgi->setThreadInfo(); while(1) {if(fcgi->readThreadFcgi(info, 10 )) {printf("go--\n"); fcgi->writeThreadFcgi(info);} std::cout<<"---"<readFcgi(info, 10)) {printf("go--\n"); fcgi->writeFcgi(info);} std::cout< <"---"<

makefile:

TARGETS=testFcgiCC=g++CFLAGS=-g -oOBJECTS=SpawnFcgi.o TestExample.oDEFINE=-DtimeOutTestLD_USR_LIBS=-L/usr/ local/lib/ -lfcgi -lpthreadINCLUDE=all: $(TARGETS)testFcgi: $(OBJECTS) $(CC) $(CFLAG S) $@ $(OBJECTS) $(LD_USR_LIBS) $(INCLUDE) $(DEFINE).cpp.o: $(CC) $(CFLAGS) $*.o $(DEFINE) $(INCLUDE) -c $*. cpp.PHONY: cleanclean: rm -rf $(OBJECTS) $(TESTDB) $(TARGETS)

Leave a Comment

Your email address will not be published.