Chinaunix首页 | 论坛 | 博客
  • 博客访问: 63257
  • 博文数量: 21
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 236
  • 用 户 组: 普通用户
  • 注册时间: 2014-09-05 21:34
文章分类

全部博文(21)

文章存档

2015年(21)

我的朋友

分类: LINUX

2015-08-07 23:53:36


点击(此处)折叠或打开

  1. //start from the very beginning,and to create greatness
  2. //@author: Chuangwei Lin
  3. //@E-mail:979951191@qq.com
  4. //@brief: SHTTPD多客户端支持的实现

  5. #include "lcw_shttpd.h"
  6. static int workersnum = 0;//工作线程的数量
  7. extern struct conf_opts conf_para;
  8. pthread_mutex_t thread_init = PTHREAD_MUTEX_INITIALIZER;//这里就已经初始化了互斥锁
  9. int WORKER_ISSTATUS(int status);
  10. static struct worker_ctl *wctls = NULL;//线程选项
  11. void Worker_Init();
  12. int Worker_Add(int i);
  13. void Worker_Delete(int i);
  14. void Worker_Destory();
  15. /******************************************************
  16. 函数名:do_work(struct worker_ctl *wctl)
  17. 参数:控制结构
  18. 功能:执行任务
  19. *******************************************************/
  20. static void do_work(struct worker_ctl *wctl)
  21. {
  22.     DBGPRINT("LCW==>do_work\n");
  23.     struct timeval tv;        //超时时间
  24.     fd_set rfds;            //读文件集
  25.     int fd = wctl->conn.cs;//客户端的套接字描述符
  26.     struct vec *req = &wctl->conn.con_req.req;//请求缓冲区向量
  27.     
  28.     int retval = 1;//返回值

  29.     for(;retval > 0;)
  30.     {
  31.         FD_ZERO(&rfds);    //清读文件集
  32.         FD_SET(fd, &rfds);//将客户端连接描述符放入读文件集
  33.         //设置超时
  34.         tv.tv_sec = 300;//conf_para.TimeOut;
  35.         tv.tv_usec = 0;
  36.         //超时读数据
  37.         retval = select(fd + 1, &rfds, NULL, NULL, &tv);
  38.         switch(retval)
  39.         {
  40.             case -1://错误
  41.                 close(fd);
  42.                 break;
  43.             case 0://超时
  44.                 close(fd);
  45.                 break;
  46.             default:
  47.                 printf("select retval:%d\n",retval);
  48.                 if(FD_ISSET(fd, &rfds))//检测文件
  49.                 {
  50.                     memset(wctl->conn.dreq, 0, sizeof(wctl->conn.dreq));
  51.                     //读取客户端数据
  52.                     req->len = read(wctl->conn.cs, wctl->conn.dreq, sizeof(wctl->conn.dreq));
  53.                     req->ptr = wctl->conn.dreq;
  54.                     DBGPRINT("Read %d bytes,'%s'\n",req->len,req->ptr);
  55.                     if(req->len > 0)
  56.                     {
  57.                         //分析客户端的数据
  58.                         wctl->conn.con_req.err = Request_Parse(wctl);//待实现
  59.                         //处理并响应客户端请求
  60.                         Request_Handle(wctl);//待实现                
  61.                     }
  62.                     else
  63.                     {
  64.                         close(fd);
  65.                         retval = -1;
  66.                     }
  67.                 }
  68.         }
  69.     }
  70.     DBGPRINT("LCW<==do_work\n");
  71. }

  72. /******************************************************
  73. 函数名:worker(void *arg)
  74. 参数:worker_ctl *wctls
  75. 功能:线程处理函数
  76. *******************************************************/
  77. static void* worker(void *arg)
  78. {
  79.     DBGPRINT("LCW==>worker\n");
  80.     struct worker_ctl *ctl = (struct worker_ctl *)arg;//为何不直接传这个类型过来?
  81.     struct worker_opts *self_opts = &ctl->opts;//定义一个选项结构
  82.     pthread_mutex_unlock(&thread_init);//解锁互斥
  83.     self_opts->flags = WORKER_IDEL;//初始化线程为空闲,等待任务
  84.     //如果主控线程没有让此线程退出,则循环处理任务
  85.     for(;self_opts->flags != WORKER_DETACHING;)//while(self_opts->flags != WORKER_DETACHING)
  86.     {
  87.         //DBGPRINT("work:%d,status:%d\n",(int)self_opts->th,self_opts->flags );
  88.         //查看是否有任务分配
  89.         int err = pthread_mutex_trylock(&self_opts->mutex);//互斥预锁定
  90.         //pthread_mutex_trylock()是pthread_mutex_lock() 的非阻塞版本
  91.         if(err)
  92.         {
  93.             //DBGPRINT("NOT LOCK\n");
  94.             sleep(1);
  95.             continue;
  96.         }
  97.         else
  98.         {
  99.             //有任务,do it
  100.             DBGPRINT("Do task\n");
  101.             self_opts->flags = WORKER_RUNNING;//执行标志
  102.             do_work(ctl);
  103.             close(ctl->conn.cs);//关闭套接字
  104.             ctl->conn.cs = -1;
  105.             if(self_opts->flags == WORKER_DETACHING)
  106.                 break;
  107.             else
  108.                 self_opts->flags = WORKER_IDEL;
  109.         }
  110.     }
  111.     //主控发送退出命令
  112.     //设置状态为已卸载
  113.     self_opts->flags = WORKER_DETACHED;
  114.     workersnum--;//工作线程-1

  115.     DBGPRINT("LCW<==worker\n");
  116.     return NULL;
  117. }
  118. /******************************************************
  119. 函数名:WORKER_ISSTATUS(int status)
  120. 参数:欲查询的线程状态
  121. 功能:查询线程状态
  122. *******************************************************/
  123. int WORKER_ISSTATUS(int status)
  124. {
  125.     int i = 0;
  126.     for(i = 0; i<conf_para.MaxClient;i++)
  127.     {
  128.         if(wctls[i].opts.flags == status)
  129.             return i;//返回符合的线程
  130.     }
  131.     return -1;//没有符合的线程状态
  132. }
  133. /*****************************************************
  134. 函数名:Worker_Init()
  135. 参数:无
  136. 功能:初始化线程    
  137. ******************************************************/
  138. void Worker_Init()
  139. {
  140.     DBGPRINT("LCW==>Worker_Init");
  141.     int i = 0;
  142.     //初始化总控参数
  143.     wctls = (struct worker_ctl*)malloc( sizeof(struct worker_ctl)*conf_para.MaxClient);//开辟空间
  144.     memset(wctls,0, sizeof(*wctls)*conf_para.MaxClient);//清零
  145.     //初始化一些参数
  146.     for(i=0;i<conf_para.MaxClient;i++)
  147.     {
  148.         //opt&connn结构和worker_ctl结构形成回指针
  149.         wctls[i].opts.work = &wctls[i];
  150.         wctls[i].conn.work = &wctls[i];
  151.         //opts结构部分的初始化
  152.         wctls[i].opts.flags = WORKER_DETACHED;
  153.         //wctls[i].opts.mutex = PTHREAD_MUTEX_INITIALIZER;
  154.         pthread_mutex_init(&wctls[i].opts.mutex,NULL);//初始化互斥锁
  155.         pthread_mutex_lock(&wctls[i].opts.mutex);
  156.         //conn部分的初始化
  157.         //con_req&con_res与conn结构形成回指
  158.         wctls[i].conn.con_req.conn = &wctls[i].conn;
  159.         wctls[i].conn.con_res.conn = &wctls[i].conn;
  160.         wctls[i].conn.cs = -1;//客户端socket连接为空
  161.         //conn.con_req部分初始化:请求结构
  162.         wctls[i].conn.con_req.req.ptr = wctls[i].conn.dreq;
  163.         wctls[i].conn.con_req.head = wctls[i].conn.dreq;
  164.         wctls[i].conn.con_req.uri = wctls[i].conn.dreq;
  165.         //conn.con_res部分初始化:响应结构
  166.         wctls[i].conn.con_res.fd = -1;
  167.         wctls[i].conn.con_res.res.ptr = wctls[i].conn.dres;

  168.     }    
  169.     for (i = 0; i < conf_para.InitClient;i++)
  170.     {
  171.         //增加规定个数工作线程
  172.         Worker_Add(i);
  173.     }
  174.     DBGPRINT("LCW<==Worker_Init\n");
  175. }

  176. /******************************************************
  177. 函数名:Worker_Add(int i)
  178. 参数:
  179. 功能:增加线程
  180. *******************************************************/
  181. int Worker_Add(int i)
  182. {
  183.     DBGPRINT("LCW==>Worker_Add\n");
  184.     pthread_t th;//线程参数
  185.     int err = -1;//返回值
  186.     if (wctls[i].opts.flags == WORKER_RUNNING)
  187.     {
  188.         return 1;//如果线程已经在工作,则返回
  189.     }
  190.     pthread_mutex_lock(&thread_init);//进入互斥区(之前有初始化过了)
  191.     wctls[i].opts.flags = WORKER_INITED;//状态为已初始化
  192.     err = pthread_create(&th, NULL, worker, (void*)&wctls[i]);//建立线程
  193.     //线程处理函数为worker
  194.     pthread_mutex_unlock(&thread_init);//解锁互斥
  195.     //更新线程选项    
  196.     wctls[i].opts.th = th;//线程ID
  197.     workersnum++;//线程数量增加1

  198.     DBGPRINT("LCW<==Worker_Add\n");
  199.     return 0;
  200. }


  201. /******************************************************
  202. 函数名:Worker_Delete(int i)
  203. 参数:线程序号
  204. 功能:减少线程
  205. *******************************************************/
  206. void Worker_Delete(int i)
  207. {
  208.     DBGPRINT("LCW==>Worker_Delete\n");
  209.     wctls[i].opts.flags = WORKER_DETACHING;//线程状态改为正在卸载
  210.     DBGPRINT("LCW<==Worker_Delete\n");
  211. }
  212. /******************************************************
  213. 函数名:Worker_Destory()
  214. 参数:
  215. 功能:销毁线程
  216. *******************************************************/
  217. void Worker_Destory()
  218. {
  219.     DBGPRINT("LCW==>Worker_Destory\n");
  220.     int i = 0;
  221.     int clean = 0;
  222.     
  223.     for(i=0;i<conf_para.MaxClient;i++)
  224.     {
  225.         DBGPRINT("thread %d,status %d\n",i,wctls[i].opts.flags );
  226.         if(wctls[i].opts.flags != WORKER_DETACHED)//如果状态不是已经卸载
  227.             Worker_Delete(i);
  228.     }

  229.     while(!clean)
  230.     {
  231.         clean = 1;
  232.         for(i = 0; i<conf_para.MaxClient;i++)
  233.         {
  234.             DBGPRINT("thread %d,status %d\n",i,wctls[i].opts.flags );
  235.             if(wctls[i].opts.flags == WORKER_RUNNING || wctls[i].opts.flags == WORKER_DETACHING)
  236.                 clean = 0;
  237.         }
  238.         if(!clean)
  239.             sleep(1);
  240.     }
  241.     DBGPRINT("LCW<==Worker_Destory\n");
  242. }

  243. //定义调度状态
  244. #define STATUS_RUNNING 1
  245. #define STATSU_STOP 0
  246. static int SCHEDULESTATUS = STATUS_RUNNING;
  247. /******************************************************
  248. 函数名:Worker_ScheduleRun(int ss)
  249. 参数:文件描述符
  250. 功能:当有客户端连接到来的时候,将客户端连接分配给空闲客户端,由客户端处理到来的请求
  251. *******************************************************/
  252. int Worker_ScheduleRun(int ss)
  253. {
  254.     DBGPRINT("LCW==>Worker_ScheduleRun!!!\n");
  255.     struct sockaddr_in client;
  256.     socklen_t len = sizeof(client);
  257.     //初始化线程服务
  258.     Worker_Init();

  259.     int i = 0;

  260.     for(;SCHEDULESTATUS== STATUS_RUNNING;)
  261.     {
  262.         struct timeval tv;//超时时间
  263.         fd_set rfds;//读文件集
  264.         //printf("SCHEDULESTATUS:%d\n",SCHEDULESTATUS);
  265.         int retval = -1;//返回值    
  266.         FD_ZERO(&rfds);    //清读文件集,将客户端连接
  267.         FD_SET(ss, &rfds);//描述符放入读文件集
  268.         //设置超时
  269.         tv.tv_sec = 0;
  270.         tv.tv_usec = 500000;
  271.         //超时读数据
  272.         retval = select(ss + 1, &rfds, NULL, NULL, &tv);
  273.         switch(retval)
  274.         {
  275.             case -1://错误
  276.             case 0://超时
  277.                 continue;
  278.                 break;
  279.             default:
  280.                 if(FD_ISSET(ss, &rfds))//检测文件
  281.                 {
  282.                     int sc = accept(ss, (struct sockaddr*)&client, &len);
  283.                     printf("client comming\n");//接受请求
  284.                     i = WORKER_ISSTATUS(WORKER_IDEL);//查找空闲业务处理线程
  285.                     if(i == -1)
  286.                     {
  287.                         i = WORKER_ISSTATUS(WORKER_DETACHED);//没有找到
  288.                         if(i != -1)
  289.                             Worker_Add(i);//增加一个业务处理线程
  290.                     }
  291.                     if(i != -1)//业务处理线程空闲,分配任务
  292.                     {
  293.                         wctls[i].conn.cs = sc;//套接字描述符
  294.                         pthread_mutex_unlock(&wctls[i].opts.mutex);//告诉业务线程有任务
  295.                     }                
  296.                 }
  297.         }        
  298.     }
  299.     
  300.     DBGPRINT("LCW<==Worker_ScheduleRun\n");
  301.     return 0;
  302. }
  303. /******************************************************
  304. 函数名:Worker_ScheduleStop()
  305. 参数:
  306. 功能:停止调度过程
  307. *******************************************************/
  308. int Worker_ScheduleStop()
  309. {
  310.     DBGPRINT("LCW==>Worker_ScheduleStop\n");
  311.     SCHEDULESTATUS = STATSU_STOP;//给任务分配线程设置终止条件
  312.     int i =0;
  313.     Worker_Destory();//销毁业务线程
  314.     int allfired = 0;
  315.     for(;!allfired;)//查询并等待业务线程终止
  316.     {
  317.         allfired = 1;
  318.         for(i = 0; i<conf_para.MaxClient;i++)
  319.         {
  320.             int flags = wctls[i].opts.flags;
  321.             if(flags == WORKER_DETACHING || flags == WORKER_IDEL)//线程正活动
  322.                 allfired = 0;
  323.         }
  324.     }
  325.     
  326.     pthread_mutex_destroy(&thread_init);//销毁互斥变量
  327.     for(i = 0; i<conf_para.MaxClient;i++)
  328.         pthread_mutex_destroy(&wctls[i].opts.mutex);//销毁业务吃力线程的互斥
  329.     free(wctls);//销毁业务数据
  330.     
  331.     DBGPRINT("LCW<==Worker_ScheduleStop\n");
  332.     return 0;
  333. }

阅读(1191) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~