zoukankan      html  css  js  c++  java
  • 一个简单的wed服务器SHTTPD(9)————main函数文件,Makefile,头文件

    主函数:

    #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
    ");
            ret = -1;
            goto EXITshttpd_listen;
        }
        //设置套接字地址和端口复用
        err = setsockopt (ss, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
        if (err == -1)
        {
            printf("setsockopt SO_REUSEADDR failed
    ");
        }
        //绑定IP和套接字描述符
        err = bind (ss, (struct sockaddr*) &server, sizeof(server));
        if (err == -1)
        {
            printf("bind() error
    ");
            ret = -2;
            goto EXITshttpd_listen;
        }
        //设置服务器侦听队列长度
        err = listen(ss, conf_para.MaxClient*2);
        if (err)
        {
            printf ("listen() error
    ");
            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;    //请求头部'结尾
        char *uri;    //请求URI,''结尾
        char rpath[URI_MAX];//请求文件的真实地址'结尾
        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服务器。

  • 相关阅读:
    Cookie和Session的那些事儿
    【IScroll深入学习】解决IScroll疑难杂症
    使用 iscroll 实现焦点图无限循环
    jquery.mobiscroll仿Iphone ActionSheet省市区联动
    mobiscroll之treelist使用
    jQuery.extend 函数详解
    jQuery插件开发精品教程,让你的jQuery提升一个台阶
    用js实现动画效果核心方式
    js特效,加速度,图标跳动
    详解用CSS3制作圆形滚动进度条动画效果
  • 原文地址:https://www.cnblogs.com/sigma0-/p/12630518.html
Copyright © 2011-2022 走看看