基于select的多并发web服务器-OPRE-HTTP

来源:互联网 发布:matlab 三维数组 画图 编辑:程序博客网 时间:2024/06/08 14:00

OPRE-HTTP-Server

  • OPRE-HTTP-Server
      • OPRE逻辑结构
      • 线程池结构
      • 相应客户端处理
        • 一并发select线程
        • 二端口无连接关闭线程
      • 并发客户端请求处理
      • http数据解析
      • opre服务器配置
      • github
      • 写在最后


OPRE逻辑结构

OPRE为了提高client连接处理速度,将响应端口请求与数据接收发送给线程池,然后继续查询是否有端口请求,而线程池接收到响应控制参数及socket值后会唤醒一个闲置的进程处理该client的数据接受及数据响应。
Created with Raphaël 2.1.0开始解析配置文件设置相关参数列表开辟线程池,并挂起所有线程开辟并挂起多个select线程开辟并挂起端口无连接检测线程设置服务器socket,bind端口listenaccept端口无连接线程挂起唤醒端口无连接线程相应select线程挂起唤醒该区块select线程数据写入socket表服务端结束释放线程池,做相关清理工作结束yesnoyesnoyesnoyesno
Created with Raphaël 2.1.0相应select线程进入查询socket区块区块无client连接相应select线程挂起client请求调用线程池工作分配函数yesnoyesno
Created with Raphaël 2.1.0线程池工作分配查询所有线程线程空闲参数丢给该线程唤醒该线程操作结束yesno
Created with Raphaël 2.1.0线程进入将参数丢给http请求处理模块标志线程空闲线程挂起
Created with Raphaël 2.1.0http解析进入recv()接受数据decode()解析http数据send()发送相应数据http解析结束
Created with Raphaël 2.1.0端口无连接关闭线程进入查询socket表状态socket表无端口连接端口无连接关闭线程挂起socket处于工作保证端口存活socket连接超时关闭端口yesnoyesnoyesno

线程池结构

线程池主要包括线程池创建,线程方法,线程挂起,线程唤醒,任务分配,线程池销毁及线程控制结构,线程池结构。
//线程控制结构体typedef struct pthread_control_struct{    //线程id    pthread_t p_ptid;    //线程信息互斥锁    pthread_mutex_t p_mutex;    //线程消息    pthread_cond_t p_cond;    //线程当前状态 0为挂起 1为运行 2为标示退出 3为线程死亡    short p_state;}pthread_ctrl_t;//线程参数结构体typedef struct pthread_member_task{    //该线程控制程序    pthread_ctrl_t *m_ptid;    //线程执行参数    //线程执行的socket    int m_socketid;    //socket控制信息    int *m_sockctrl;    //任务状态信息    int *m_isintask;    //主目录路径    char *m_dirpath;}pthread_mtask_t;//线程池结构体typedef struct pthread_pool_struct{    //线程控制数组指针    pthread_ctrl_t *o_ptpool;    //线程参数数组指针    pthread_mtask_t *o_ptmem;    //线程池中线程总数目    int o_ptsum;    //设置访问阻塞    pthread_mutex_t mutex;}pthread_pool_t;

相应客户端处理

select、close线程与主线程共享同一个client连接处理结构体,主要控制服务器所处理的所有数据。设置一个结构体原因主要是方便数据管理与精简的参数传递。
//client连接处理结构体typedef struct server_socekt_deal_struct{    //主文件夹路径    char *d_dirpath;    //客户端最大数量    int d_maxlink;    //客户端当前数量    int d_curlink;    //客户端序列表    int *d_clisok;    //客户端连接信息 0为连接断开 1为连接中    int *d_lstate;    //客户端任务执行状态 0为未执行任务 1为正在执行    int *d_task;    //客户端可连接位置    int d_liloc;    //客户端连接时间 超时关闭用    long *d_linktime;    //连接超时时长    int d_otime;    //select用的数据    int d_maxsoc;    fd_set d_fds;    struct timeval d_timeout;    //线程池    pthread_pool_t *d_pool;    //线程状态相关信息    pthread_ctrl_t *d_ctrl;    //select线程条数    int d_selsum;}server_sds_t;

一、并发select线程

服务器存在多个select线程,每个线程处理不同的socket区块,设置select控制结构体用于区分线程所处理socket区块。
//select线程控制结构体typedef struct SelectCtrlStr{    //控制结构    server_sds_t *s_sds;    //线程select号    int s_selectid;}select_ctrl;

二、端口无连接关闭线程

端口关闭并设置端口控制标记
//端口号sds->d_clisok[i]=-1;//连接时间sds->d_linktime[i]=0;//连接状态sds->d_lstate[i]=0;//任务状态sds->d_task[i]=0;//连接数量--sds->d_curlink;

并发客户端请求处理

一个线程只处理一个客户端请求,并响应该请求。
//线程参数结构体typedef struct pthread_member_task{    //该线程控制程序    pthread_ctrl_t *m_ptid;    //线程执行参数    //线程执行的socket    int m_socketid;    //socket控制信息    int *m_sockctrl;    //任务状态信息    int *m_isintask;    //主目录路径    char *m_dirpath;}pthread_mtask_t;

http数据解析

目前OPRE更多关注主体架构,目前只允许静态页面与各类型文件传输请求,目前OPRE将http请求数据解析存储与请求数据结构体中。并且由于业务逻辑的独立性,在请求响应可以根据自己需求修改,可加入gzip压缩模块,php解析模块,由于服务器处于多线程中,不支持CGI,但可以扩展为以socket通讯的cgi方式。
//http请求值typedef struct HTTPREENV{    //请求方法    char REQUEST_METHOD[8];    //如果是get存get值最大是1024    char QUERY_STRING[1025];    //如果是post自行开辟空间    char *POST_STRING;    //post数据长度    char CONTENT_LENGTH[16];    //用户信息    char USER_AGENT[256];    //http请求类型 content-type 类型传输    char HTTP_ACCEPT[256];    //用户请求文件路径    char REQUEST_PATH[256];    //连接类型 keep-alive close    char CONNECT_TYPE[32];    //http协议    char HTTP_PCTL[16];    //Accept-Encoding gzip类型压缩的东西    char ACCEPT_ENCODE[256];}httpenv_t;//文件缓存结构体typedef struct FILESEND{    char *fbuff;    int fsize;}fsend_t;

opre服务器配置

OPRE配置文件支持#注释

#最大客户端连接数linksum = 100#客户端链接存活时间existtime = 6#最多同时处理客户端数目clientsum = 10#服务器监听ip地址lishost = 192.168.11.122#服务器监听端口号lisport = 8081#目录的路径(.为当前目录)homepath = ./inside

github

相关工程代码会上传到github

写在最后

由于在开发OPRE过程中发现select的种种问题,近期会用epoll重写,并将会服务器与响应端彻底分开,以便支持分布式环境,如此服务器相当与一个转发端,将数据接接收后发往一个或多个不同的响应端,响应端数据处理后向服务器提交数据后再由服务器转发。以此来提高服务器并发量,以及实现一个服务器便可管理多个网站。
原创粉丝点击