主函数:

#include "lcw_shttpd.h"

//初始化时服务器的默认配置
extern struct conf_opts conf_para=
{
"/usr/local/var/www/cgi-bin/",//CGI根目录
"index.html",//默认文件名称
"/usr/local/var/www/",//根文件目录
"/etc/SHTTPD.conf",//配置文件路径和名称
8080, //监听端口
4, //最大客户端数量
3,//超时时间
2//初始化线程数量
};
struct vec _shttpd_methods[] = {
{"GET", 3, METHOD_GET},
{"POST", 4, METHOD_POST},
{"PUT", 3, METHOD_PUT},
{"DELETE", 6, METHOD_DELETE},
{"HEAD", 4, METHOD_HEAD},
{NULL, 0}
};
/******************************************************
函数名:sig_int(int num)
参数:
功能:SIGINT信号截取函数
*******************************************************/
static void sig_int(int num)
{
Worker_ScheduleStop();
return;
}
/******************************************************
函数名:
参数:
功能:SIGPIPE信号截取函数
*******************************************************/
static void sig_pipe(int num)
{
return;
}
/******************************************************
函数名:do_listen()
参数:
功能:套接字初始化
*******************************************************/
int do_listen()
{
struct sockaddr_in server;
int ss = -1;
int err = -1;
int reuse = 1;
int ret = -1;
// 初始化服务器地址
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr=htonl(INADDR_ANY);
server.sin_port = htons(conf_para.ListenPort);
//信号截取函数
signal(SIGINT, sig_int);
signal(SIGPIPE, sig_pipe);
//生成套接字文件描述符
ss = socket (AF_INET, SOCK_STREAM, 0);
if (ss == -1)
{
printf("socket() error\n");
ret = -1;
goto EXITshttpd_listen;
}
//设置套接字地址和端口复用
err = setsockopt (ss, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
if (err == -1)
{
printf("setsockopt SO_REUSEADDR failed\n");
}
//绑定IP和套接字描述符
err = bind (ss, (struct sockaddr*) &server, sizeof(server));
if (err == -1)
{
printf("bind() error\n");
ret = -2;
goto EXITshttpd_listen;
}
//设置服务器侦听队列长度
err = listen(ss, conf_para.MaxClient*2);
if (err)
{
printf ("listen() error\n");
ret = -3;
goto EXITshttpd_listen;
} ret = ss;
EXITshttpd_listen:
return ret;
} int l_main()
{
int ss = -1;
ss = do_listen();
return 0;
}
/******************************************************
函数名:main(int argc, char *argv[])
参数:
功能:主函数
*******************************************************/
int main(int argc, char *argv[])
{
signal(SIGINT, sig_int);//挂接信号
Para_Init(argc,argv);//参数初始化
int s = do_listen();//套接字初始化
Worker_ScheduleRun(s);//任务调度
return 0;
}

头文件:

//start from the very beginning,and to create greatness
//@author: Chuangwei Lin
//@E-mail:979951191@qq.com
//@brief: SHTTPD服务器的实现:主要的数据结构
//配置文件的结构//
#ifndef _LCW_SHTTP_H_
#define _LCW_SHTTP_H_
#include <stdio.h>
#include <getopt.h>//getopt_long()函数所在库函数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <netinet/in.h> // for sockaddr_in
#include <netdb.h> // for hostent
#include <pthread.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h> // we want to catch some of these after all
#include <unistd.h> // protos for read, write, close, etc
#include <dirent.h> // for MAXNAMLEN
#include <limits.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <stddef.h>
#define big_int_t long
#define URI_MAX 16384 // Default max request size
//线程的状态值
enum
{
WORKER_INITED,//初始化
WORKER_RUNNING,//正在执行
WORKER_DETACHING,//正在卸载
WORKER_DETACHED,//已经卸载
WORKER_IDEL//空闲
};
struct conf_opts
{
char CGIRoot[128]; //CGI根目录
char DefaultFile[128]; //默认文件名称
char DocumentRoot[128]; //根文件目录
char ConfigFile[128]; //配置文件路径和名称
int ListenPort; //监听端口
int MaxClient; //最大客户端数量
int TimeOut; //超时时间
int InitClient; //初始化线程数量
};
// HTTP协议的方法
typedef enum SHTTPD_METHOD_TYPE{
METHOD_GET, //GET方法
METHOD_POST, //POST方法
METHOD_PUT, //PUT方法
METHOD_DELETE, //DELETE方法
METHOD_HEAD, //HEAD方法
METHOD_CGI, //CGI方法
METHOD_NOTSUPPORT
}SHTTPD_METHOD_TYPE; enum {HDR_DATE, HDR_INT, HDR_STRING};//HTTP头部类型 typedef struct shttpd_method
{
SHTTPD_METHOD_TYPE type;
int name_index;
}shttpd_method; typedef struct vec
{
char* ptr;//字符串
int len;//字符串长度
SHTTPD_METHOD_TYPE type;//字符串表示类型
}vec; struct http_header {
int len; //Header name length
int type; // Header type
size_t offset; // Value placeholder
char* name; // Header name
}; // This structure tells how HTTP headers must be parsed.
// Used by parse_headers() function.
#define OFFSET(x) offsetof(struct headers, x) union variant {
char* v_str;
int v_int;
big_int_t v_big_int;
time_t v_time;
void (*v_func)(void);
void *v_void;
struct vec v_vec;
}; //头部结构
struct headers
{
union variant cl; //内容长度
union variant ct; //内容类型
union variant connection; //连接状态
union variant ims; //最后修改时间
union variant user; //用户名称
union variant auth; //权限
union variant useragent; //用户代理
union variant referer; //参考
union variant cookie; //Cookie
union variant location; //位置
union variant range; //范围
union variant status; //状态值
union variant transenc; //编码类型
}; struct cgi{
int iscgi;
struct vec bin;
struct vec para;
};
struct worker_ctl;//要先声明
struct worker_opts{
pthread_t th; //线程的ID号
int flags; //线程状态
pthread_mutex_t mutex;//线程任务互斥
struct worker_ctl *work;//本线程的总控结构
};
struct worker_conn;//要先声明
//请求结构
struct conn_request{
struct vec req;//请求向量
char *head; //请求头部\0'结尾
char *uri; //请求URI,'\0'结尾
char rpath[URI_MAX];//请求文件的真实地址\0'结尾
int method; //请求类型
//HTTP的版本信息
unsigned long major;//主版本
unsigned long minor;//副版本
struct headers ch;//头部结构
struct worker_conn *conn;//连接结构指针
int err;
};
//响应结构
struct conn_response{
struct vec res; //响应向量
time_t birth_time; //建立时间
time_t expire_time;//超时时间
int status; //响应状态值
int cl; //响应内容长度
int fd; //请求文件描述符
struct stat fsate; //请求文件状态
struct worker_conn *conn;//连接结构指针
};
struct worker_conn
{
#define K 1024
char dreq[16*K]; //请求缓冲区
char dres[16*K]; //响应缓冲区
int cs; //客户端套接字文件描述符
int to; //客户端无响应时间超时退出时间
struct conn_response con_res;
struct conn_request con_req;
struct worker_ctl *work; //本线程的总控结构
}; struct worker_ctl
{
struct worker_opts opts;//用于表示线程的状态
struct worker_conn conn;//用于表示客户端请求的状态和值
}; //文件内容的类型格式
struct mine_type{
char* extension;//扩展名
int type;//类型
int ext_len;//扩展名长度
char* mime_type;//内容类型
}; void Para_Init(int argc, char *argv[]);
int Request_Parse(struct worker_ctl *wctl);
int Request_Handle(struct worker_ctl* wctl); int Worker_ScheduleRun();
int Worker_ScheduleStop();
void Method_Do(struct worker_ctl *wctl);
void uri_parse(char *src, int len);
struct mine_type* Mine_Type(char *uri, int len, struct worker_ctl *wctl); #define DBGPRINT printf
#endif

Makefile:

CFLAGS = -Wall -g
LIBS = -lpthread
TARGET = lcw_shttpd
RM = rm -f
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
all:$(OBJS)
gcc -o $(TARGET) $(OBJS) $(LIBS)
clean:
$(RM) $(TARGET) $(OBJS)

书上的代码其实有很多错误,网上下载的源码好像有些地方也是有点怪怪的。编译可以通过,运行的时候,在浏览器上输入主机IP,有显示访问,dowork,但是默认的html没有运行。因为知识还不是很熟练,所以打算再熟悉下HTTP协议,以及学习另一个web服务器。

一个简单的wed服务器SHTTPD(9)————main函数文件,Makefile,头文件的更多相关文章

  1. 一个简单的wed服务器SHTTPD(1)————命令行和文件配置解析

    开始学习<LInux网络编程>中的综合案例,虽然代码书上有,还是自己打一下加深理解和印象. 主要有两个函数,完成命令行的解析,另一个实现配置文件的解析,注释还是比较丰富的哦. //star ...

  2. 一个简单的wed服务器SHTTPD(5)————服务器SHTTPD请求方法解析

    //start from the very beginning,and to create greatness //@author: Chuangwei Lin //@E-mail:979951191 ...

  3. 一个简单的wed服务器SHTTPD(6)———— SHTTPD错误处理的实现

    //start from the very beginning,and to create greatness //@author: Chuangwei Lin //@E-mail:979951191 ...

  4. 一个简单的wed服务器SHTTPD(4)————SHTTPD支持CGI的实现

    //start from the very beginning,and to create greatness //@author: Chuangwei Lin //@E-mail:979951191 ...

  5. 一个简单的wed服务器SHTTPD(3)————SHTTPD多客户端支持的实现

    //start from the very beginning,and to create greatness //@author: Chuangwei Lin //@E-mail:979951191 ...

  6. 一个简单的wed服务器SHTTPD(8)———— URI分析

    //start from the very beginning,and to create greatness //@author: Chuangwei Lin //@E-mail:979951191 ...

  7. 一个简单的wed服务器SHTTPD(7)———— SHTTPD内容类型的实现

    //start from the very beginning,and to create greatness //@author: Chuangwei Lin //@E-mail:979951191 ...

  8. 一个简单的wed服务器SHTTPD(2)———— 客户端请求分析

    //start from the very beginning,and to create greatness //@author: Chuangwei Lin //@E-mail:979951191 ...

  9. 一个简单的web服务器

    写在前面 新的一年了,新的开始,打算重新看一遍asp.net本质论这本书,再重新认识一下,查漏补缺,认认真真的过一遍. 一个简单的web服务器 首先需要引入命名空间: System.Net,关于网络编 ...

随机推荐

  1. 11-Json提取器使用

    1.使用json提取关键信息 有时候接口返回数据为json数据或者直接为一个列表,可使用这个更简单快捷 json数据: 这样的,数据有在result里面以列表形式存在,也有在列表外的,可在json提取 ...

  2. MySQL锁---InnoDB行锁需要注意的细节

    前言 换了工作之后,接近半年没有发博客了(一直加班),emmmm.....今天好不容易有时间,记录下工作中遇到的一些问题,接下来应该重拾知识点了.因为新公司工作中MySQL库经常出现查询慢,锁等待,节 ...

  3. 列表推导式和seed()的理解

    Table of Contents generated with DocToc 列表推导式和seed()的理解 对seed()的理解 列表推导式 第一种用法 第二种用法 列表推导式和seed()的理解 ...

  4. 树状数组模板--Color the ball

    Color the ball HDU - 1556 N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电 ...

  5. 有关google的guava工具包详细说明

    Guava 中文是石榴的意思,该项目是 Google 的一个开源项目,包含许多 Google 核心的 Java 常用库. 目前主要包含: com.google.common.annotations c ...

  6. Tomcat5启动流程与配置详解

    标签:配置 tomcat 休闲 职场 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://zhangjunhd.blog.51cto. ...

  7. 数据结构和算法(Golang实现)(25)排序算法-快速排序

    快速排序 快速排序是一种分治策略的排序算法,是由英国计算机科学家Tony Hoare发明的, 该算法被发布在1961年的Communications of the ACM 国际计算机学会月刊. 注:A ...

  8. AJ学IOS(22)UI之UIApplicationDelegate和UIWindow

    AJ分享,必须精品 UIApplicationDelegate 每次新建完项目,都有个带有“AppDelegate”字眼的类,它就是UIApplication的代理 NYAppDelegate默认已经 ...

  9. 复杂Excel转换与导入

    需求 把不同客户提供Excel 直接导入到系统中生成对应的收货单或是出货单.后端创建收货端和出货单的接口已经有现成的webservice或是标准的xml:这类需要做的就是把客户提供不同种类的Excel ...

  10. Android调用系统设置

    最近,弄了一下,调用系统设置的方法,Android4.0的系统,下面的所有设置项,都亲测可以调用.首先调用的方式如下: Intent mintent_setting_time = new Intent ...