-
//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 0
-
static 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;
-
}
阅读(1236) | 评论(0) | 转发(0) |