1. 简介:
tinyhttpd是使用c语言开发的超轻量级http服务器,通过代码流程可以了解http服务器的基本处理流程,
并且涉及了网络套接字,线程,父子进程,管道等等知识点;
项目地址:http://sourceforge.net/projects/tinyhttpd/
2. 流程介绍:
(1) 服务器启动,等待客户端请求到来;
(2) 客户端请求到来,创建新线程处理该请求;
(3) 读取httpHeader中的method,截取url,其中GET方法需要记录url问号之后的参数串;
(4) 根据url构造完整路径,如果是/结尾,则指定为该目录下的index.html;
(5) 获取文件信息,如果找不到文件,返回404,找到文件则判断文件权限;
(6) 如果是GET请求并且没有参数,或者文件不可执行,则直接将文件内容构造http信息返回给客户端;
(7) 如果是GET带参数,POST,文件可执行,则执行CGI;
(8) GET请求略过httpHeader,POST方法需要记录httpHeader中的Content-Length:xx;
(9) 创建管道用于父子进程通信,fork产生子进程;
(10) 子进程设置环境变量,将标准输入和输出与管道相连,并且通过exec执行CGI;
(11) 如果是POST,父进程将读到post内容发送给子进程,并且接收子进程的输出,输出给客户端;
3. 管道说明:
4. 代码注释:
1 /* J. David's webserver */ 2 /* This is a simple webserver. 3 * Created November 1999 by J. David Blackstone. 4 * CSE 4344 (Network concepts), Prof. Zeigler 5 * University of Texas at Arlington 6 */ 7 /* This program compiles for Sparc Solaris 2.6. 8 * To compile for Linux: 9 * 1) Comment out the #include <pthread.h> line. 10 * 2) Comment out the line that defines the variable newthread. 11 * 3) Comment out the two lines that run pthread_create(). 12 * 4) Uncomment the line that runs accept_request(). 13 * 5) Remove -lsocket from the Makefile. 14 */ 15 #include <stdio.h> 16 #include <sys/socket.h> 17 #include <sys/types.h> 18 #include <netinet/in.h> 19 #include <arpa/inet.h> 20 #include <unistd.h> 21 #include <ctype.h> 22 #include <strings.h> 23 #include <string.h> 24 #include <sys/stat.h> 25 #include <pthread.h> 26 #include <sys/wait.h> 27 #include <stdlib.h> 28 29 #define ISspace(x) isspace((int)(x)) 30 31 #define SERVER_STRING "Server: jdbhttpd/0.1.0 " 32 33 void accept_request(int); 34 void bad_request(int); 35 void cat(int, FILE *); 36 void cannot_execute(int); 37 void error_die(const char *); 38 void execute_cgi(int, const char *, const char *, const char *); 39 int get_line(int, char *, int); 40 void headers(int, const char *); 41 void not_found(int); 42 void serve_file(int, const char *); 43 int startup(u_short *); 44 void unimplemented(int); 45 46 /**********************************************************************/ 47 /* A request has caused a call to accept() on the server port to 48 * return. Process the request appropriately. 49 * Parameters: the socket connected to the client */ 50 /**********************************************************************/ 51 void accept_request(int client) 52 { 53 char buf[1024]; 54 int numchars; 55 char method[255]; 56 char url[255]; 57 char path[512]; 58 size_t i, j; 59 struct stat st; 60 int cgi = 0; /* becomes true if server decides this is a CGI 61 * program */ 62 char *query_string = NULL; 63 64 //读取第一行数据 65 numchars = get_line(client, buf, sizeof(buf)); 66 i = 0; j = 0; 67 //读取http的头部method字段,读到空白为止 68 while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) 69 { 70 method[i] = buf[j]; 71 i++; j++; 72 } 73 method[i] = '