一个简单的wed服务器SHTTPD(3)————SHTTPD多客户端支持的实现

来源:互联网 发布:java词典 编辑:程序博客网 时间:2024/06/05 17:31
//start from the very beginning,and to create greatness//@author: Chuangwei Lin//@E-mail:979951191@qq.com//@brief: SHTTPD多客户端支持的实现#include "lcw_shttpd.h"static int workersnum = 0;//工作线程的数量extern struct conf_opts conf_para;pthread_mutex_t thread_init = PTHREAD_MUTEX_INITIALIZER;//这里就已经初始化了互斥锁int WORKER_ISSTATUS(int status);static struct worker_ctl *wctls = NULL;//线程选项void Worker_Init();int Worker_Add(int i);void Worker_Delete(int i);void Worker_Destory();/******************************************************函数名:do_work(struct worker_ctl *wctl)参数:控制结构功能:执行任务*******************************************************/static void do_work(struct worker_ctl *wctl){    DBGPRINT("LCW==>do_work\n");    struct timeval tv;        //超时时间    fd_set rfds;            //读文件集    int fd = wctl->conn.cs;//客户端的套接字描述符    struct vec *req = &wctl->conn.con_req.req;//请求缓冲区向量    int retval = 1;//返回值    for(;retval > 0;)    {        FD_ZERO(&rfds);    //清读文件集        FD_SET(fd, &rfds);//将客户端连接描述符放入读文件集        //设置超时        tv.tv_sec = 300;//conf_para.TimeOut;        tv.tv_usec = 0;        //超时读数据        retval = select(fd + 1, &rfds, NULL, NULL, &tv);        switch(retval)        {            case -1://错误                close(fd);                break;            case 0://超时                close(fd);                break;            default:                printf("select retval:%d\n",retval);                if(FD_ISSET(fd, &rfds))//检测文件                {                    memset(wctl->conn.dreq, 0, sizeof(wctl->conn.dreq));                    //读取客户端数据                    req->len = read(wctl->conn.cs, wctl->conn.dreq, sizeof(wctl->conn.dreq));                    req->ptr = wctl->conn.dreq;                    DBGPRINT("Read %d bytes,'%s'\n",req->len,req->ptr);                    if(req->len > 0)                    {                        //分析客户端的数据                        wctl->conn.con_req.err = Request_Parse(wctl);//待实现                        //处理并响应客户端请求                        Request_Handle(wctl);//待实现                                    }                    else                    {                        close(fd);                        retval = -1;                    }                }        }    }    DBGPRINT("LCW<==do_work\n");}/******************************************************函数名:worker(void *arg)参数:worker_ctl *wctls功能:线程处理函数*******************************************************/static void* worker(void *arg){    DBGPRINT("LCW==>worker\n");    struct worker_ctl *ctl = (struct worker_ctl *)arg;//为何不直接传这个类型过来?    struct worker_opts *self_opts = &ctl->opts;//定义一个选项结构    pthread_mutex_unlock(&thread_init);//解锁互斥    self_opts->flags = WORKER_IDEL;//初始化线程为空闲,等待任务    //如果主控线程没有让此线程退出,则循环处理任务    for(;self_opts->flags != WORKER_DETACHING;)//while(self_opts->flags != WORKER_DETACHING)    {        //DBGPRINT("work:%d,status:%d\n",(int)self_opts->th,self_opts->flags );        //查看是否有任务分配        int err = pthread_mutex_trylock(&self_opts->mutex);//互斥预锁定        //pthread_mutex_trylock()是pthread_mutex_lock() 的非阻塞版本        if(err)        {            //DBGPRINT("NOT LOCK\n");            sleep(1);            continue;        }        else        {            //有任务,do it            DBGPRINT("Do task\n");            self_opts->flags = WORKER_RUNNING;//执行标志            do_work(ctl);            close(ctl->conn.cs);//关闭套接字            ctl->conn.cs = -1;            if(self_opts->flags == WORKER_DETACHING)                break;            else                self_opts->flags = WORKER_IDEL;        }    }    //主控发送退出命令    //设置状态为已卸载    self_opts->flags = WORKER_DETACHED;    workersnum--;//工作线程-1    DBGPRINT("LCW<==worker\n");    return NULL;}/******************************************************函数名:WORKER_ISSTATUS(int status)参数:欲查询的线程状态功能:查询线程状态*******************************************************/int WORKER_ISSTATUS(int status){    int i = 0;    for(i = 0; i<conf_para.MaxClient;i++)    {        if(wctls[i].opts.flags == status)            return i;//返回符合的线程    }    return -1;//没有符合的线程状态}/*****************************************************函数名:Worker_Init()参数:无功能:初始化线程    ******************************************************/void Worker_Init(){    DBGPRINT("LCW==>Worker_Init");    int i = 0;    //初始化总控参数    wctls = (struct worker_ctl*)malloc( sizeof(struct worker_ctl)*conf_para.MaxClient);//开辟空间    memset(wctls,0, sizeof(*wctls)*conf_para.MaxClient);//清零    //初始化一些参数    for(i=0;i<conf_para.MaxClient;i++)    {        //opt&connn结构和worker_ctl结构形成回指针        wctls[i].opts.work = &wctls[i];        wctls[i].conn.work = &wctls[i];        //opts结构部分的初始化        wctls[i].opts.flags = WORKER_DETACHED;        //wctls[i].opts.mutex = PTHREAD_MUTEX_INITIALIZER;        pthread_mutex_init(&wctls[i].opts.mutex,NULL);//初始化互斥锁        pthread_mutex_lock(&wctls[i].opts.mutex);        //conn部分的初始化        //con_req&con_res与conn结构形成回指        wctls[i].conn.con_req.conn = &wctls[i].conn;        wctls[i].conn.con_res.conn = &wctls[i].conn;        wctls[i].conn.cs = -1;//客户端socket连接为空        //conn.con_req部分初始化:请求结构        wctls[i].conn.con_req.req.ptr = wctls[i].conn.dreq;        wctls[i].conn.con_req.head = wctls[i].conn.dreq;        wctls[i].conn.con_req.uri = wctls[i].conn.dreq;        //conn.con_res部分初始化:响应结构        wctls[i].conn.con_res.fd = -1;         wctls[i].conn.con_res.res.ptr = wctls[i].conn.dres;    }        for (i = 0; i < conf_para.InitClient;i++)    {        //增加规定个数工作线程        Worker_Add(i);    }    DBGPRINT("LCW<==Worker_Init\n");}/******************************************************函数名:Worker_Add(int i)参数:功能:增加线程*******************************************************/int Worker_Add(int i){    DBGPRINT("LCW==>Worker_Add\n");    pthread_t th;//线程参数    int err = -1;//返回值    if (wctls[i].opts.flags == WORKER_RUNNING)    {        return 1;//如果线程已经在工作,则返回    }    pthread_mutex_lock(&thread_init);//进入互斥区(之前有初始化过了)    wctls[i].opts.flags = WORKER_INITED;//状态为已初始化    err = pthread_create(&th, NULL, worker, (void*)&wctls[i]);//建立线程    //线程处理函数为worker    pthread_mutex_unlock(&thread_init);//解锁互斥    //更新线程选项        wctls[i].opts.th = th;//线程ID    workersnum++;//线程数量增加1    DBGPRINT("LCW<==Worker_Add\n");    return 0;}/******************************************************函数名:Worker_Delete(int i)参数:线程序号功能:减少线程*******************************************************/void Worker_Delete(int i){    DBGPRINT("LCW==>Worker_Delete\n");    wctls[i].opts.flags = WORKER_DETACHING;//线程状态改为正在卸载    DBGPRINT("LCW<==Worker_Delete\n");}/******************************************************函数名:Worker_Destory()参数:功能:销毁线程*******************************************************/void Worker_Destory(){    DBGPRINT("LCW==>Worker_Destory\n");    int i = 0;    int clean = 0;    for(i=0;i<conf_para.MaxClient;i++)    {        DBGPRINT("thread %d,status %d\n",i,wctls[i].opts.flags );        if(wctls[i].opts.flags != WORKER_DETACHED)//如果状态不是已经卸载            Worker_Delete(i);    }    while(!clean)    {        clean = 1;        for(i = 0; i<conf_para.MaxClient;i++)        {            DBGPRINT("thread %d,status %d\n",i,wctls[i].opts.flags );            if(wctls[i].opts.flags == WORKER_RUNNING || wctls[i].opts.flags == WORKER_DETACHING)                clean = 0;        }        if(!clean)            sleep(1);    }    DBGPRINT("LCW<==Worker_Destory\n");}//定义调度状态#define STATUS_RUNNING 1#define STATSU_STOP 0static int SCHEDULESTATUS = STATUS_RUNNING;/******************************************************函数名:Worker_ScheduleRun(int ss)参数:文件描述符功能:当有客户端连接到来的时候,将客户端连接分配给空闲客户端,由客户端处理到来的请求*******************************************************/int Worker_ScheduleRun(int ss){    DBGPRINT("LCW==>Worker_ScheduleRun!!!\n");    struct sockaddr_in client;    socklen_t len = sizeof(client);    //初始化线程服务    Worker_Init();    int i = 0;    for(;SCHEDULESTATUS== STATUS_RUNNING;)    {        struct timeval tv;//超时时间        fd_set rfds;//读文件集        //printf("SCHEDULESTATUS:%d\n",SCHEDULESTATUS);        int retval = -1;//返回值            FD_ZERO(&rfds);    //清读文件集,将客户端连接        FD_SET(ss, &rfds);//描述符放入读文件集        //设置超时        tv.tv_sec = 0;        tv.tv_usec = 500000;        //超时读数据        retval = select(ss + 1, &rfds, NULL, NULL, &tv);        switch(retval)        {            case -1://错误            case 0://超时                continue;                break;            default:                if(FD_ISSET(ss, &rfds))//检测文件                {                    int sc = accept(ss, (struct sockaddr*)&client, &len);                    printf("client comming\n");//接受请求                    i = WORKER_ISSTATUS(WORKER_IDEL);//查找空闲业务处理线程                    if(i == -1)                    {                        i = WORKER_ISSTATUS(WORKER_DETACHED);//没有找到                        if(i != -1)                            Worker_Add(i);//增加一个业务处理线程                    }                    if(i != -1)//业务处理线程空闲,分配任务                    {                        wctls[i].conn.cs = sc;//套接字描述符                        pthread_mutex_unlock(&wctls[i].opts.mutex);//告诉业务线程有任务                    }                                }        }            }    DBGPRINT("LCW<==Worker_ScheduleRun\n");    return 0;}/******************************************************函数名:Worker_ScheduleStop()参数:功能:停止调度过程*******************************************************/int Worker_ScheduleStop(){    DBGPRINT("LCW==>Worker_ScheduleStop\n");    SCHEDULESTATUS = STATSU_STOP;//给任务分配线程设置终止条件    int i =0;    Worker_Destory();//销毁业务线程    int allfired = 0;    for(;!allfired;)//查询并等待业务线程终止    {        allfired = 1;        for(i = 0; i<conf_para.MaxClient;i++)        {            int flags = wctls[i].opts.flags;            if(flags == WORKER_DETACHING || flags == WORKER_IDEL)//线程正活动                allfired = 0;        }    }    pthread_mutex_destroy(&thread_init);//销毁互斥变量    for(i = 0; i<conf_para.MaxClient;i++)        pthread_mutex_destroy(&wctls[i].opts.mutex);//销毁业务吃力线程的互斥    free(wctls);//销毁业务数据    DBGPRINT("LCW<==Worker_ScheduleStop\n");    return 0;}
0 0