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

全部博文(21)

文章存档

2015年(21)

我的朋友

分类: LINUX

2015-08-08 00:06:48

主函数:

点击(此处)折叠或打开

  1. #include "lcw_shttpd.h"

  2. //初始化时服务器的默认配置
  3. extern struct conf_opts conf_para=
  4. {
  5.     "/usr/local/var/www/cgi-bin/",//CGI根目录
  6.     "index.html",//默认文件名称
  7.     "/usr/local/var/www/",//根文件目录
  8.     "/etc/SHTTPD.conf",//配置文件路径和名称
  9.     8080, //监听端口
  10.     4, //最大客户端数量
  11.     3,//超时时间
  12.     2//初始化线程数量
  13. };
  14. struct vec _shttpd_methods[] = {
  15.     {"GET",        3, METHOD_GET},
  16.     {"POST",        4, METHOD_POST},
  17.     {"PUT",        3, METHOD_PUT},
  18.     {"DELETE",    6, METHOD_DELETE},
  19.     {"HEAD",        4, METHOD_HEAD},
  20.     {NULL,        0}
  21. };
  22. /******************************************************
  23. 函数名:sig_int(int num)
  24. 参数:
  25. 功能:SIGINT信号截取函数
  26. *******************************************************/
  27. static void sig_int(int num)
  28. {
  29.     Worker_ScheduleStop();
  30.     return;
  31. }
  32. /******************************************************
  33. 函数名:
  34. 参数:
  35. 功能:SIGPIPE信号截取函数
  36. *******************************************************/
  37. static void sig_pipe(int num)
  38. {
  39.     return;
  40. }
  41. /******************************************************
  42. 函数名:do_listen()
  43. 参数:
  44. 功能:套接字初始化
  45. *******************************************************/
  46. int do_listen()
  47. {
  48.     struct sockaddr_in server;
  49.     int ss = -1;
  50.     int err = -1;
  51.     int reuse = 1;
  52.     int ret = -1;
  53.     // 初始化服务器地址
  54.     memset(&server, 0, sizeof(server));
  55.     server.sin_family = AF_INET;
  56.     server.sin_addr.s_addr=htonl(INADDR_ANY);
  57.     server.sin_port = htons(conf_para.ListenPort);
  58.     //信号截取函数
  59.     signal(SIGINT, sig_int);
  60.     signal(SIGPIPE, sig_pipe);
  61.     //生成套接字文件描述符
  62.     ss = socket (AF_INET, SOCK_STREAM, 0);
  63.     if (ss == -1)
  64.     {
  65.         printf("socket() error\n");
  66.         ret = -1;
  67.         goto EXITshttpd_listen;
  68.     }
  69.     //设置套接字地址和端口复用
  70.     err = setsockopt (ss, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
  71.     if (err == -1)
  72.     {
  73.         printf("setsockopt SO_REUSEADDR failed\n");
  74.     }
  75.     //绑定IP和套接字描述符
  76.     err = bind (ss, (struct sockaddr*) &server, sizeof(server));
  77.     if (err == -1)
  78.     {
  79.         printf("bind() error\n");
  80.         ret = -2;
  81.         goto EXITshttpd_listen;
  82.     }
  83.     //设置服务器侦听队列长度
  84.     err = listen(ss, conf_para.MaxClient*2);
  85.     if (err)
  86.     {
  87.         printf ("listen() error\n");
  88.         ret = -3;
  89.         goto EXITshttpd_listen;
  90.     }

  91.     ret = ss;
  92. EXITshttpd_listen:
  93.     return ret;
  94. }

  95. int l_main()
  96. {
  97.     int ss = -1;
  98.     ss = do_listen();
  99.     return 0;
  100. }
  101. /******************************************************
  102. 函数名:main(int argc, char *argv[])
  103. 参数:
  104. 功能:主函数
  105. *******************************************************/
  106. int main(int argc, char *argv[])
  107. {
  108.     signal(SIGINT, sig_int);//挂接信号
  109.     Para_Init(argc,argv);//参数初始化
  110.     int s = do_listen();//套接字初始化
  111.     Worker_ScheduleRun(s);//任务调度
  112.     return 0;
  113. }
头文件:

点击(此处)折叠或打开

  1. //start from the very beginning,and to create greatness
  2. //@author: Chuangwei Lin
  3. //@E-mail:979951191@qq.com
  4. //@brief: SHTTPD服务器的实现:主要的数据结构
  5. //配置文件的结构//
  6. #ifndef _LCW_SHTTP_H_
  7. #define _LCW_SHTTP_H_
  8. #include <stdio.h>
  9. #include <getopt.h>//getopt_long()函数所在库函数
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <time.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <sys/socket.h>
  17. #include <sys/wait.h>
  18. #include <sys/time.h>
  19. #include <netinet/in.h> // for sockaddr_in
  20. #include <netdb.h> // for hostent
  21. #include <pthread.h>
  22. #include <arpa/inet.h>
  23. #include <signal.h>
  24. #include <errno.h> // we want to catch some of these after all
  25. #include <unistd.h> // protos for read, write, close, etc
  26. #include <dirent.h> // for MAXNAMLEN
  27. #include <limits.h>
  28. #include <getopt.h>
  29. #include <unistd.h>
  30. #include <sys/types.h>
  31. #include <sys/stat.h>
  32. #include <fcntl.h>
  33. #include <ctype.h>
  34. #include <stddef.h>
  35. #define big_int_t long
  36. #define    URI_MAX        16384        // Default max request size    
  37. //线程的状态值
  38. enum
  39. {
  40.     WORKER_INITED,//初始化
  41.     WORKER_RUNNING,//正在执行
  42.     WORKER_DETACHING,//正在卸载
  43.     WORKER_DETACHED,//已经卸载
  44.     WORKER_IDEL//空闲
  45. };
  46. struct conf_opts
  47. {
  48.     char CGIRoot[128]; //CGI根目录
  49.     char DefaultFile[128]; //默认文件名称
  50.     char DocumentRoot[128]; //根文件目录
  51.     char ConfigFile[128]; //配置文件路径和名称
  52.     int ListenPort; //监听端口
  53.     int MaxClient; //最大客户端数量
  54.     int TimeOut; //超时时间
  55.     int InitClient; //初始化线程数量
  56. };
  57. // HTTP协议的方法
  58. typedef enum SHTTPD_METHOD_TYPE{
  59.     METHOD_GET,     //GET方法
  60.     METHOD_POST,     //POST方法
  61.     METHOD_PUT,     //PUT方法
  62.     METHOD_DELETE,     //DELETE方法
  63.     METHOD_HEAD,    //HEAD方法
  64.     METHOD_CGI,        //CGI方法
  65.     METHOD_NOTSUPPORT
  66. }SHTTPD_METHOD_TYPE;

  67. enum {HDR_DATE, HDR_INT, HDR_STRING};//HTTP头部类型

  68. typedef struct shttpd_method
  69. {
  70.     SHTTPD_METHOD_TYPE type;
  71.     int name_index;    
  72. }shttpd_method;

  73. typedef struct vec
  74. {
  75.     char* ptr;//字符串
  76.     int    len;//字符串长度
  77.     SHTTPD_METHOD_TYPE type;//字符串表示类型
  78. }vec;

  79. struct http_header {
  80.     int    len;        //Header name length        
  81.     int    type;        // Header type        
  82.     size_t    offset;    // Value placeholder        
  83.     char* name;        // Header name        
  84. };

  85.  // This structure tells how HTTP headers must be parsed.
  86.  // Used by parse_headers() function.
  87. #define    OFFSET(x)    offsetof(struct headers, x)

  88. union variant {
  89.     char* v_str;
  90.     int    v_int;
  91.     big_int_t v_big_int;
  92.     time_t    v_time;
  93.     void (*v_func)(void);
  94.     void *v_void;
  95.     struct vec v_vec;
  96. };

  97. //头部结构
  98. struct headers
  99.  {
  100.     union variant    cl;         //内容长度
  101.     union variant    ct;         //内容类型
  102.     union variant    connection; //连接状态
  103.     union variant    ims;        //最后修改时间
  104.     union variant    user;     //用户名称
  105.     union variant    auth;        //权限
  106.     union variant    useragent; //用户代理
  107.     union variant    referer;    //参考
  108.     union variant    cookie;        //Cookie
  109.     union variant    location; //位置
  110.     union variant    range;        //范围
  111.     union variant    status;        //状态值
  112.     union variant    transenc;    //编码类型
  113. };

  114. struct cgi{
  115.     int iscgi;
  116.     struct vec bin;
  117.     struct vec para;    
  118. };
  119. struct worker_ctl;//要先声明
  120. struct worker_opts{
  121.     pthread_t th;            //线程的ID号
  122.     int flags;                //线程状态
  123.     pthread_mutex_t mutex;//线程任务互斥
  124.     struct worker_ctl *work;//本线程的总控结构
  125. };
  126. struct worker_conn;//要先声明
  127. //请求结构
  128. struct conn_request{
  129.     struct vec    req;//请求向量
  130.     char *head;    //请求头部\0'结尾
  131.     char *uri;    //请求URI,'\0'结尾
  132.     char rpath[URI_MAX];//请求文件的真实地址\0'结尾
  133.     int method;    //请求类型
  134.     //HTTP的版本信息
  135.     unsigned long major;//主版本
  136.     unsigned long minor;//副版本
  137.     struct headers ch;//头部结构
  138.     struct worker_conn *conn;//连接结构指针
  139.     int err;
  140. };
  141. //响应结构
  142. struct conn_response{
  143.     struct vec    res;    //响应向量
  144.     time_t birth_time;    //建立时间
  145.     time_t expire_time;//超时时间
  146.     int    status;        //响应状态值
  147.     int    cl;            //响应内容长度
  148.     int fd;        //请求文件描述符
  149.     struct stat fsate;    //请求文件状态
  150.     struct worker_conn *conn;//连接结构指针    
  151. };
  152. struct worker_conn
  153. {
  154.     #define K 1024
  155.     char dreq[16*K];    //请求缓冲区
  156.     char dres[16*K];    //响应缓冲区
  157.     int    cs;            //客户端套接字文件描述符
  158.     int    to;            //客户端无响应时间超时退出时间
  159.     struct conn_response con_res;
  160.     struct conn_request con_req;
  161.     struct worker_ctl *work;    //本线程的总控结构
  162. };

  163. struct worker_ctl
  164. {
  165.     struct worker_opts opts;//用于表示线程的状态
  166.     struct worker_conn conn;//用于表示客户端请求的状态和值
  167. };

  168. //文件内容的类型格式
  169. struct mine_type{
  170.     char* extension;//扩展名
  171.     int type;//类型
  172.     int    ext_len;//扩展名长度
  173.     char* mime_type;//内容类型
  174. };


  175. void Para_Init(int argc, char *argv[]);
  176. int Request_Parse(struct worker_ctl *wctl);
  177. int Request_Handle(struct worker_ctl* wctl);

  178. int Worker_ScheduleRun();
  179. int Worker_ScheduleStop();
  180. void Method_Do(struct worker_ctl *wctl);
  181. void uri_parse(char *src, int len);
  182. struct mine_type* Mine_Type(char *uri, int len, struct worker_ctl *wctl);



  183. #define DBGPRINT printf
  184. #endif
Makefile:

点击(此处)折叠或打开

  1. CFLAGS = -Wall -g
  2. LIBS = -lpthread
  3. TARGET = lcw_shttpd
  4. RM = rm -f
  5. OBJS = lcw_shttpd_parameters.o lcw_shttpd.o lcw_shttpd_worker.o lcw_shttpd_uri.o lcw_shttpd_request.o lcw_shttpd_method.o lcw_shttpd_mine.o lcw_shttpd_error.o
  6. all:$(OBJS)
  7. gcc -o $(TARGET) $(OBJS) $(LIBS)
  8. clean:
  9. $(RM) $(TARGET) $(OBJS)
书上的代码其实有很多错误,网上下载的源码好像有些地方也是有点怪怪的。编译可以通过,运行的时候,在浏览器上输入主机IP,有显示访问,dowork,但是默认的html没有运行。因为知识还不是很熟练,所以打算再熟悉下HTTP协议,以及学习另一个web服务器。

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