Skip to content
This repository has been archived by the owner on Feb 12, 2022. It is now read-only.

Commit

Permalink
进程池,用进程池实现的简单CGI服务器
Browse files Browse the repository at this point in the history
  • Loading branch information
hihaha committed Mar 15, 2014
1 parent fce5da7 commit 7e35923
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 2 deletions.
162 changes: 162 additions & 0 deletions 15-2-process-pool-cgi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/stat.h>

#include "processpool.h"

//用于处理客户端CGI请求的类,它可以作为processpool类的模板参数
//
class cgi_conn
{
public:
cgi_conn() {}
~cgi_conn(){}

//初始化客户连接,清空读缓冲区
void init(int epollfd, int sockfd, const sockaddr_in &client_addr)
{
m_epollfd = epollfd;
m_sockfd = sockfd;
m_address = client_addr;
memset(m_buf, '\0', BUFFER_SIZE);
m_read_idx = 0;
}

void process()
{
int idx = 0;
int ret = -1;
//循环读取和分析客户数据
while(true)
{
idx = m_read_idx;
ret = recv(m_sockfd, m_buf + idx, BUFFER_SIZE - 1 - idx, 0);
//如果读操作发生错误,则关闭客户连接。但如果是暂时无数据可读,则退出循环
if (ret < 0)
{
if (errno != EAGAIN)
{
removefd(m_epollfd, m_sockfd);
}
break;
}
//如果对方关闭连接,则服务器也关闭连接
else if (ret == 0)
{
removefd(m_epollfd, m_sockfd);
break;
}
else
{
m_read_idx += ret;
fprintf(stdout, "user content is: %s\n", m_buf);
//如果遇到字符“\r\n”, 则开始处理客户请求
for(;idx < m_read_idx; ++idx)
{
if ((idx >= 1) && (m_buf[idx-1] == '\r') && (m_buf[idx] == '\n'))
{
break;
}
}
//如果没有遇到字符“\r\n”,则需要读取更多客户数据
if (idx == m_read_idx)
{
continue;
}
m_buf[idx - 1] = '\0';

char *file_name = m_buf;
//判断客户要运行的CGI程序是否存在
if (access(file_name, F_OK) == -1)
{
removefd(m_epollfd, m_sockfd);
break;
}
//创建子进程来执行CGI程序
ret = fork();
if (ret == -1)
{
removefd(m_epollfd, m_sockfd);
break;
}
else if (ret > 0)
{
//父进程只需关闭连接
removefd(m_epollfd, m_sockfd);
break;
}
else
{
//子进程将标准输出定向到m_sockfd, 并执行CGI程序
close(STDOUT_FILENO);
dup(m_sockfd);
execl(m_buf, m_buf, (char *)0);
exit(0);
}
}
}
}

private:
//读缓冲区的大小
static const int BUFFER_SIZE = 1024;
static int m_epollfd;
int m_sockfd;
sockaddr_in m_address;
char m_buf[BUFFER_SIZE];
//标记读缓冲区中已经读入的客户数据的最后一个字节的下一个位置
int m_read_idx;
};

int cgi_conn::m_epollfd = -1;


int main(int argc, const char *argv[])
{

if (argc <= 2)
{
fprintf(stdout, "usage: %s ip_address port_number\n", basename(argv[0]));
return 1;
}
const char *ip = argv[1];
int port = atoi(argv[2]);

int listenfd = socket(PF_INET, SOCK_STREAM, 0);
assert(listenfd >= 0);

int ret = 0;
struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port);

ret = bind(listenfd, (struct sockaddr*)&address, sizeof(address));
assert( ret != -1);

ret = listen(listenfd, 5);
assert( ret != -1);

processpool<cgi_conn> * pool = processpool<cgi_conn>::create(listenfd);
if (pool)
{
pool->run();
delete pool;
}
close(listenfd); //main 函数创建了文件描述符listenfd,那么就由它亲自关闭
return 0;
}
2 changes: 1 addition & 1 deletion mk.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ g++ 13-5-send-fd.c -o send-fd
g++ 14-1-dead-lock.c -o dea-lock -lpthread
g++ 14-3-multi-thread-fork.c -o multi-thread-fork -lpthread
g++ 14-5-thread-handle-signal.c -o threadhandlesignal -lpthread

g++ processpool.h 15-2-process-pool-cgi.c -o process-pool-cgi
5 changes: 4 additions & 1 deletion processpool.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ class processpool
static processpool<T> *m_instance;
};

template< typename T>
processpool<T> *processpool<T>::m_instance = NULL;

//pipe used to handle signal
static int sig_pipefd[2];

Expand Down Expand Up @@ -144,7 +147,7 @@ processpool<T>::processpool(int listenfd, int process_number)
for(int i = 0; i < process_number; i++)
{
int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, m_sub_process[i].m_pipefd);
assert(ret = 0);
assert(ret == 0);

m_sub_process[i].m_pid = fork();
assert(m_sub_process[i].m_pid >= 0);
Expand Down

0 comments on commit 7e35923

Please sign in to comment.