zoukankan      html  css  js  c++  java
  • 一个简单的wed服务器SHTTPD(1)————命令行和文件配置解析

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

    //start from the very beginning,and to create greatness
    //@author: Chuangwei Lin
    //@E-mail:979951191@qq.com
    //@brief: 命令行解析代码和配置文件解析的实现
    
    #include "lcw_shttpd.h"
    
    //短选项的配置为c:d:f:h:o:l:m:t:
    static char* shortopts="c:d:f:h:o:l:m:t:";
    //长选项的配置
    //option是getop_long的一个结构体参数p531
    static struct option longopts[]=
    {
        {"CGIRoot",required_argument,NULL,'c'},
        {"ConfigFile",required_argument,NULL,'f'},
        {"DefaultFile",required_argument,NULL,'d'},
        {"DocumentRoot",required_argument,NULL,'o'},
        {"ListenPort",required_argument,NULL,'l'},
        {"MaxClient",required_argument,NULL,'m'},
        {"TimeOut",required_argument,NULL,'t'},
        {"Help",no_argument,NULL,'h'},
        {0,0,0,0},
    }
    //初始化时服务器的默认配置
    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//初始化线程数量
    };
    /******************************************************
    函数名:display_usage(void)
    参数:无
    功能:显示参数输入方法
    *******************************************************/
    void display_usage(void)
    {
        printf("*******************Chuangwei Lin*******************
    ");
        printf("sHTTPD -l number -m number -o path -c path -d filename -t seconds -o filename
    ");
        printf("sHTTPD --ListenPort number
    ");
        printf(" --MaxClient number
    ");
        printf(" --DocumentRoot) path
    ");
        printf(" --DefaultFile) filename
    ");
        printf(" --CGIRoot path 
    ");
        printf(" --DefaultFile filename
    ");
        printf(" --TimeOut seconds
    ");
        printf(" --ConfigFile filename
    ");
    }
    /******************************************************
    函数名:conf_readline(int fd, char *buff, int len)
    参数:文件描述符,缓冲区,长度
    功能:读取配置文件的一行
    *******************************************************/
    static int conf_readline(int fd, char *buff, int len)
    {
        int n = -1;
        int i = 0;
        int begin = 0;
        memset(buff, 0, len);//清缓冲区
        for(i =0; i<len;begin?i++:i)//当开头部分不为'
    '或者'
    '时i计数
        { //begin真则i++
            n = read(fd, buff+i, 1);//读一个字符
            if(n == 0)//文件末尾
            {
                *(buff+i) = '';
                break;
            }
            else if(*(buff+i) == '
    ' ||*(buff+i) == '
    ')
            {//是回车换行
                if(begin)
                {//为一行
                    *(buff+i) = '';    
                    break;
                }
            }
            else
            {
                begin = 1;
            }
        }
        return i;
    }
    
    static char* l_opt_arg;//存输入参数
    /******************************************************
    函数名:Para_CmdParse(int argc,char* argv[])
    参数:argc:参数个数 ,argv:参数的字符串数组,两个参数一般是从main()函数的输入参数中直接传来
    功能:命令行解析函数,利用getopt_long函数实现
    *******************************************************/
    static int Para_CmdParse(int argc,char* argv[])
    {
        int c;
        int len;
        int value;
        //遍历输入参数,设置配置参数
        while((c=getopt_long(argc,argv,shortopts,longopts,NULL))!=-1)
        {    
            switch(c)    
            { //getopt_long()如果有输入参数,则输入参数为optarg
                case:'c'//CGI跟路径
                 l_opt_arg = optarg;
                 if (l_opt_arg && l_opt_arg[0] != ':')
                 {
                     len = strlen(l_opt_arg);
                     memcpy(conf_para.CGIRoot,l_opt_arg,len+1);//更新
                 }
                    break;
                case:'d'//默认文件名称
                 l_opt_arg = optarg;
                 if (l_opt_arg && l_opt_arg[0] != ':')
                 {
                     len = strlen(l_opt_arg);
                     memcpy(conf_para.DefaultFile,l_opt_arg,len+1);
                 }
                    break;
                case:'f'//配置文件名称和路径
                 l_opt_arg = optarg;
                 if (l_opt_arg && l_opt_arg[0] != ':')
                 {
                     len = strlen(l_opt_arg);
                     memcpy(conf_para.ConfigFile,l_opt_arg,len+1);
                 }
                    break;
                case:'o'//根文件路径
                 l_opt_arg = optarg;
                 if (l_opt_arg && l_opt_arg[0] != ':')
                 {
                     len = strlen(l_opt_arg);
                     memcpy(conf_para.DocumentRoot,l_opt_arg,len+1);
                 }
                    break;
                case:'l'//侦听端口
                 l_opt_arg = optarg;
                 if (l_opt_arg && l_opt_arg[0] != ':')
                 {
                     len = strlen(l_opt_arg);
                     value = strtol(l_opt_arg,NULL,10);//转化字符串为整形
                     if (value != LONG_MAX && value != LONG_MIN)
                     {
                         conf_para.ListenPort = value;//更新
                     }
                 }
                    break;
                case:'m'//最大客户端数量
                 l_opt_arg = optarg;
                 if (l_opt_arg && l_opt_arg[0] != ':')
                 {
                     len = strlen(l_opt_arg);
                     value = strtol(l_opt_arg,NULL,10);//转化字符串为整形
                     if (value != LONG_MAX && value != LONG_MIN)
                     {
                         conf_para.MaxClient = value;//更新
                     }
                 }
                    break;
                case:'t'//超时时间
                 l_opt_arg = optarg;
                 if (l_opt_arg && l_opt_arg[0] != ':')
                 {
                     len = strlen(l_opt_arg);
                     value = strtol(l_opt_arg,NULL,10);//转化字符串为整形
                     if (value != LONG_MAX && value != LONG_MIN)
                     {
                         conf_para.TimeOut = value;//更新
                     }
                 }
                    break;
                case:'?'
                    printf("Invalid para 
    ");
                case:'h'
                    display_usage();
                    break;
            }
        }
    } 
    /******************************************************
    函数名:Para_FileParse(char* file)
    参数:文件
    功能:文件配置解析函数
    *******************************************************/
    void Para_FileParse(char* file)
    {
        #define LINELENGTH 256
        char line[LINELENGTH];//读取缓冲区
        char *name = NULL,*value = NULL;//用于获取关键字和值
        int fd = -1;//文件描述符
        int n = 0;
        fd = open(file,O_RDONLY);//只读方式打开配置文件
        if (-1 == fd)//错误检查
        {
            goto EXITPara_FileParse;//退出
        }
        //命令格式如下
        //[#注释|[空格]关键字[空格]=[空格]value]
        //
        while((n = conf_readline(fd,line,LINELENGTH))!= 0)//每次读取一行
        {
            char *pos = line;//文件位置指针
            while(isspace(*pos))
            {
                pos++;//跳过一行开头部分的空格
            }
            if(*pos == '#')//如果是注释
            {
                continue;//那就读取下一行
            }
            name = pos;//此时的位置就是关键字的开头
            while(!isspace(*pos) && *pos != '=')//不是空格也不是’=‘,则继续读直到读完关键字
            {
                pos++;
            }
            *pos = '';//得到关键字
            while(isspace(*pos))//再次跳过值前面的空格
            {
                pos++;
            }
            value = pos;
            while(!isspace(*pos) && *pos != '
    ' && *pos != '
    ')//读到结束
            {
                pos++;
            }
            pos = '';//得到值
            //根据关键字,将值赋给配置文件的结构
            int ivalue;
            if(strncmp("CGIRoot",name,7))
            {
                memcpy(conf_para.CGIRoot,value,strlen(value)+1);
            }
            else if(strncmp("DefaultFile",name,11))
            {
                memcpy(conf_para.DefaultFile,value,strlen(value)+1);
            }
            else if(strncmp("DocumentRoot",name,12))
            {
                memcpy(conf_para.DocumentRoot,value,strlen(value)+1);
            }
            else if(strncmp("ListenPort",name,10))
            {
                ivalue = strtol(value,NULL,10);//转化字符串为整形
                conf_para.ListenPort = ivalue;
            }
            else if(strncmp("MaxClient",name,9))
            {
                ivalue = strtol(value,NULL,10);//转化字符串为整形
                conf_para.MaxClient = ivalue;
            }
            else if(strncmp("TimeOut",name,7))
            {
                ivalue = strtol(value,NULL,10);//转化字符串为整形
                conf_para.TimeOut = ivalue;
            }
    
        }
        close(fd);//关闭文件
    EXITPara_FileParse:
        return ;
    }
    /******************************************************
    函数名:display_para()
    参数:无
    功能:显示配置的参数
    *******************************************************/
    static void display_para()
    {
        printf("*******************Chuangwei Lin*******************
    ");
        printf("sHTTPD ListenPort: %d
    ",conf_para.ListenPort);
        printf(" MaxClient: %d
    ", conf_para.MaxClient);
        printf(" DocumentRoot: %s
    ",conf_para.DocumentRoot);
        printf(" DefaultFile:%s
    ",conf_para.DefaultFile);
        printf(" CGIRoot:%s 
    ",conf_para.CGIRoot);
        printf(" DefaultFile:%s
    ",conf_para.DefaultFile);
        printf(" TimeOut:%d
    ",conf_para.TimeOut);
        printf(" ConfigFile:%s
    ",conf_para.ConfigFile);
    }
    /******************************************************
    函数名:Para_Init(int argc, char *argv[])
    参数:参数个数,和参数字符串
    功能:初始化配置
    *******************************************************/
    void Para_Init(int argc, char *argv[])
    {
        //解析命令行输入参数
        Para_CmdParse(argc, argv);
        //解析配置文件配置参数 
        if(strlen(conf_para.ConfigFile))
         {
             Para_FileParse(conf_para.ConfigFile);
         }
        display_para();
        return ;//返回配置参数
    }
  • 相关阅读:
    WampServer Mysql配置
    Java实现 蓝桥杯VIP 算法提高 陶陶摘苹果2
    Java实现 蓝桥杯VIP 算法提高 陶陶摘苹果2
    Java实现 蓝桥杯VIP 算法提高 陶陶摘苹果2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 前10名
  • 原文地址:https://www.cnblogs.com/sigma0-/p/12630526.html
Copyright © 2011-2022 走看看