ocesspool ppool; int main() { int listenfd = Socket_create( "192.168.1.250", 8888 ); init_process_pool( &ppool, MAXPROCESSNUMBER, USERPERPROCESS, MAXEPOLLEVENT, 5, listenfd ); run( &ppool ); close( listenfd ); return 0; }
贴一下makefile:
CC = gcc ROOTDIR = $(shell pwd) OBJ = util.o myhshappool.o epoll_wrapper.o \ client_handle.o cgisrc.o BIN = cgisrv.bin CFLAG = -Wall -O2 -I./ LDFLAG += -c $(BIN):${OBJ} $(CC) $(CFLAG) -o $@ $^ %:%.c $(CC) $(CFLAG) -o $@ $< $(LDFLAG) .PHONY:clean clean: rm $(OBJ) $(BIN) -rf
还有cgi执行程序:
#include
#include
#include
/*
..
*/ int main( int argc, char **argv ) { time_t tt = time(NULL); printf(""); printf(""); printf(""); printf("
"); printf("
"); printf(""); printf(""); printf("
"); printf("当前服务器时间:%s", ctime(&tt)); printf("
"); printf(""); printf(""); return 0; }
测试:代码编译了,即可执行cgisrv.bin,主进程处于监听客户端连接情况,打开浏览器输入: http://xxx.xxx.xxx.xxx:8888/now.cgi,可以看到出现一行加下划线的绿字:当前服务器时间:Sat Sep 17 21:49:07 2016。
ip、端口、进程池数、最大epoll监听事件数等在入口模块(cgisrv)可以改。
模型的简单介绍:主进程创建几个子进程作为工作进程,主进程监听客户端connect事件,一旦有连接事件,即通过round robin(简单轮询)选取一个子进程, 通过父子进程间的通信管道通知子进程有连接事件,子进程epoll监听到管道通信时间,即知道有客户端连接,因此进程accept,并将客户端连接套接字加入epoll监听事件,客户端浏览器发送get请求,客户端监听到请求事件,即调用封装好的客户端事件进行处理,本例子的客户端处理为recv客户的请求,从中提取文件名(now.cgi),并重定向客户端连接套接字到stdout,然后执行对应cgi文件,cgi文件打印html页面字符串,因为重定向的缘故,打印的html字符串发送给客户端,客户端浏览器即显示了html页面。
本例子写完,调试了几个地方,运行几个客户端发送get请求就没有做测试了,因此也不知道高并发是否会跑出bug(epoll模型+进程池处理上百上千的并发应该不是问题,主要是怕我代码有bug),其实应当弄个压力测试来跑一下的,不过也没时间弄了,还要学习半同步半反应堆的模型。