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

OPRE-HTTP-Server


OPRE逻辑结构

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

线程池结构

线程池主要包括线程池创建,线程方法,线程挂起,线程唤醒,任务分配,线程池销毁及线程控制结构,线程池结构。
//线程控制结构体
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重写,并将会服务器与响应端彻底分开,以便支持分布式环境,如此服务器相当与一个转发端,将数据接接收后发往一个或多个不同的响应端,响应端数据处理后向服务器提交数据后再由服务器转发。以此来提高服务器并发量,以及实现一个服务器便可管理多个网站。
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值