1 /**************************************************************************** 2 * 3 * tinyhttpd-0.1.0_hacking 4 * 5 * 1.这是tinyhttpd-0.1.0版本中httpd.c(主程序)的源码,源码不到500行(除去注释). 6 * 2.通过分析、阅读该源码,可以一窥web服务器的大致工作机制. 7 * 3.知识量: 8 * 1.C语言; 9 * 2.Unix或类Unix系统编程; 10 * 3.微量的http协议(请求行、消息头、实体内容); 11 * 4.如何阅读别人的代码( 从main函数开始 :) ); 12 * 4.tinyhttpd-0.1.0 文件结构如下: 13 * . 14 * |-- Makefile -------->makefile 文件 15 * |-- README -------->说明文档 16 * |-- htdocs -------->程序会到该文件夹下找对应html、cgi文件 17 * | |-- README -------->说明文档 18 * | |-- check.cgi -------->cgi 程序 19 * | |-- color.cgi ----^ 20 * | `-- index.html -------->默认的 web 首页文件 21 * |-- httpd.c -------->你接下来要阅读的文件 22 * `-- simpleclient.c -------->没发现该文件有任何用处 @_@ 23 * 5.如何阅读该文档: 24 * 1.linux下使用vi/vim配和ctags,windows下使用Source Insight,当然你也 25 * 可以用其他文本编辑器看. 26 * 2.先找到main函数,然后就可以开始阅读了,遇到对应的函数,就去看对应的 27 * 函数. 28 * 3.对于有些函数,本人没有添加注释,或者说本人觉得没必要. 29 * 4.祝您好运. :) 30 * 31 * 6.tinyhttpd-0.1.0版本下载url: http://sourceforge.net/projects/tinyhttpd/ 32 * 33 * 如果您对本文有任何意见、提议,可以发邮件至zengjf42@163.com,会尽快回复. 34 * 本文的最终解释权归本人(曾剑锋)所有,仅供学习、讨论. 35 * 36 * 2015-3-1 阴 深圳 尚观 Var 37 * 38 ***************************************************************************/ 39 40 41 /* J. David's webserver */ 42 /* This is a simple webserver. 43 * Created November 1999 by J. David Blackstone. 44 * CSE 4344 (Network concepts), Prof. Zeigler 45 * University of Texas at Arlington 46 */ 47 /* This program compiles for Sparc Solaris 2.6. 48 * To compile for Linux: 49 * 1) Comment out the #include <pthread.h> line. 50 * 2) Comment out the line that defines the variable newthread. 51 * 3) Comment out the two lines that run pthread_create(). 52 * 4) Uncomment the line that runs accept_request(). 53 * 5) Remove -lsocket from the Makefile. 54 */ 55 #include <stdio.h> 56 #include <sys/socket.h> 57 #include <sys/types.h> 58 #include <netinet/in.h> 59 #include <arpa/inet.h> 60 #include <unistd.h> 61 #include <ctype.h> 62 #include <strings.h> 63 #include <string.h> 64 #include <sys/stat.h> 65 #include <pthread.h> 66 #include <sys/wait.h> 67 #include <stdlib.h> 68 69 #define ISspace(x) isspace((int)(x)) 70 71 #define SERVER_STRING "Server: jdbhttpd/0.1.0 " 72 73 void accept_request(int); 74 void bad_request(int); 75 void cat(int, FILE *); 76 void cannot_execute(int); 77 void error_die(const char *); 78 void execute_cgi(int, const char *, const char *, const char *); 79 int get_line(int, char *, int); 80 void headers(int, const char *); 81 void not_found(int); 82 void serve_file(int, const char *); 83 int startup(u_short *); 84 void unimplemented(int); 85 86 /** 87 * accept_request 函数说明: 88 * 1.获取请求方式,目前只支持GET、POST请求; 89 * 2.在本程序中所有的POST请求、带参数的GET请求都都被定义为访问cgi程序; 90 * 3.从带参数的GET请求中分离出请求参数; 91 * 4.如果没有指定需要访问的文件,使用index.html文件作为默认访问文件; 92 * 5.检查需要访问的文件是否存在,以及其是否具有对应的权限; 93 * 6.根据是否是cgi程序访问,来执行对应的任务. 94 */ 95 void accept_request(int client) 96 { 97 /** 98 * 局部变量说明: 99 * 1.buf : buffer缩写,主要用于暂存从socket中读出来的数据; 100 * 2.numchars : 用于保存每次从socket中读到的字符的个数; 101 * 3.method : 用于保存请求方式,目前该软件只支持GET、POST这两种方式; 102 * 4.url : 用于保存访问文件信息,有些地方叫uri; 103 * 5.path : 用于保存文件路径; 104 * 6.i, j : 处理数据时的下标; 105 * 7.st : 在判断文件类型、是否存在的时候用到; 106 * 8.cgi : 是否调用cgi程序的标志. 107 */ 108 char buf[1024]; 109 int numchars; 110 char method[255]; 111 char url[255]; 112 char path[512]; 113 size_t i, j; 114 struct stat st; 115 int cgi = 0; /* becomes true if server decides this is a CGI 116 * program */ 117 char *query_string = NULL; 118 119 /** 120 * 判断程序是否是GET、POST请求两种的其中一种,如果不是则报错. 121 */ 122 numchars = get_line(client, buf, sizeof(buf)); 123 i = 0; j = 0; 124 while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) 125 { 126 method[i] = buf[j]; 127 i++; j++; 128 } 129 method[i] = '