剖析进程池和线程池实现CGI服务器及Web服务器
目录
1.处理多客户任务
2.实现CGL服务器
3.线程池web服务器
一、项目当中并发服务器(动态创建子进程或子线程),存在缺点?
1、动态创建进程(或线程)是比较耗费时间,导致较慢的客户响应;2、动态创建子进程(或子线程)通常只用来为一个客户服务,导致系统产生大量进程(线程),进程(线程)切换消耗大量的CPU时间;3、动态创建的子进程是当前进程的完整映像。
二、进程池和线程池
前面我给大家讲过httpd守护进程就是使用包含7个子进程的进程池来实现并发操作。线程池中的线程数量应用和CPU数量差不多。主进程选择那个子进程为新任务服务,拥有两种方式来解决?使用算法主动选择子进程。常用简单随机算法和Round Robin(轮流选取)算法。
如图:
三、如何处埋多客户在使用进程池处理多客户任务的时候,首先要考虑的是:监听socket和连接socket是否都由主进程来统一管理(半同步/半反应堆模式)。多个子进程处理同一个客户连接上不同任务数据?
如图:
1 #include <stdio.h>2 #include <sys/types.h>3 #include <sys/socket.h>4 #include <netinet/in.h>5 #include <arpa/inet.h>6 #include <assert.h>7 #include <unistd.h>8 #include <errno.h>9 #include <string.h>10 #include <stdlib.h>11 #include <fcntl.h>12 #include <sys/epoll.h>13 #include <signal.h>14 #include <sys/wait.h>1516
1617 #include'procspool.h'/*引用已设计好的进程池*/1819/*处理客户CGI请求类的设计,它也可以设计作为类模板参数应用*/20 class cgi_conn21{22=public:23 cgi_conn(){}24 ~cgi_conn(){)25s/*初始化客户连接,清空读缓冲区数据信息*/26void int(int epollfd, int sockfd, const sockaddr_in &client_addr)27 {2830 }33=private:/*读取缓冲区的大小*/static const int BUFFER_SIZE=2048;36 static int m_epollfd;37 int m sockfd;38 sockaddr_in m_address;39 char m_buf[BUFFER_SIZE];40/*标记读缓冲中已经计入的客户数据的最后一个字节的下一位置*/41 int m_read_index;
while(true)idx=m_read_index;ret=recv(m_sockfd,m_buf+idx,BUFFER_SIZE-1-idx,0);/*如果读操作发生错误,则关闭客户连接。但如果暂时无数据可读,则退出循环*/if(ret<0){if(errno!=EAGEIN)removefd(m_epollfd,m_sockfd);break ;
48 aif(errno!=EAGEIN)49removefd(m_epollfd,m_sockfd);50break;5152/*如果对方关闭连接,则服务器也关闭连接*/53else if(ret==0)54a{55if(errno!=EAGEIN)56removefd(m_epollfd,m_sockfd);57break;58}59else60={61m_read_idx=m_read_indx+ret;62printf('User content is:%s\n',m_buf);/*如果遇到字符\r\n,则开始处理客户请求*/for(;idx<=m_read_idx;++idx)6566日if((idx>=1)&&(m_buf[idx-1]=='\r')&&(m_buf[idx]=='\n'))break;68/如果没有遇到字符\r\n,则需要读取更多客户数据*/70if(idx==m_read_idx)71=con73
赞 (0)