概述
这里就不细述了,代码很简单.
其实现的功能比较若,可以做一个参考.
因为其通过文件的权限
位来判断是否是一个CGI
脚本,所以在权限位不对的情况下会判断不正确.例如我将这个目录放置在NTFS分区,所有的文件都有可执行权限,会导致将index.html
文件当做CGI脚本.
注释后的文件在这里下载http://files.cnblogs.com/files/oloroso/tinyhttpd-0.1.0.tar.7z
/* J. David's webserver */
/* This is a simple webserver.
* Created November 1999 by J. David Blackstone.
* CSE 4344 (Network concepts), Prof. Zeigler
* University of Texas at Arlington
*/
/* This program compiles for Sparc Solaris 2.6.
* To compile for Linux:
* 1) Comment out the #include <pthread.h> line.
* 2) Comment out the line that defines the variable newthread.
* 3) Comment out the two lines that run pthread_create().
* 4) Uncomment the line that runs accept_request().
* 5) Remove -lsocket from the Makefile.
*/
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ctype.h>
#include <strings.h>
#include <string.h>
#include <sys/stat.h>
#include <pthread.h>
#include <sys/wait.h>
#include <stdlib.h>
#define ISspace(x) isspace((int)(x))
#define SERVER_STRING "Server: jdbhttpd/0.1.0rn"
// 接受请求,并处理
void accept_request(int clientsockfd);
// 无法处理请求,回写400到client
void bad_request(int);
// 将文件内容发送到client
void cat(int client, FILE* fp);
// 不可以执行CGI程序,回写500到client
void cannot_execute(int);
// 输出错误信息
void error_die(const char *);
// 执行cgi程序
void execute_cgi(int, const char *, const char *, const char *);
// 从fd中读取一行,并将读取的'rn'和'r'转换为'n'
int get_line(int fd, char* buf, int bufsize);
// 返回200 OK给客户端
void headers(int clientsockfd, const char * filename);
// 返回404状态给客户端
void not_found(int);
// 处理客户端文件请求,发送404或200+文件内容到client
void serve_file(int client, const char* filename);
// 开启soket监听
int startup(u_short *);
// 返回501状态给客户端
void unimplemented(int);
/**********************************************************************/
/* A request has caused a call to accept() on the server port to
* return. Process the request appropriately.
* Parameters: the socket connected to the client */
/**********************************************************************/
void accept_request(int client)
{
char buf[1024];
int numchars;
char method[255]; // 方法(请求类型)
char url[255]; // 请求的资源URL
char path[512]; // 请求资源的本地路径
size_t i, j;
struct stat st;
int cgi = 0; /* becomes true if server decides this is a CGI program */
/* 为真时,表示服务器需调用一个CGI程序 */
char *query_string = NULL;
// 1. 从客户端连接请求数据包中读取一行
numchars = get_line(client, buf, sizeof(buf));
// 2. 从读取的数据中提取出请求类型
i = 0; j = 0;
while (!ISspace(buf[j]) && (i < sizeof(method) - 1))
{
method[i] = buf[j];
i++; j++;
}
method[i] = '