当前位置:   article > 正文

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

一个简单的wed服务器shttpd

开始学习《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*******************\n");
    printf("sHTTPD -l number -m number -o path -c path -d filename -t seconds -o filename\n");
    printf("sHTTPD --ListenPort number\n");
    printf(" --MaxClient number\n");
    printf(" --DocumentRoot) path\n");
    printf(" --DefaultFile) filename\n");
    printf(" --CGIRoot path \n");
    printf(" --DefaultFile filename\n");
    printf(" --TimeOut seconds\n");
    printf(" --ConfigFile filename\n");
}
/******************************************************
函数名: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)//当开头部分不为'\r'或者'\n'时i计数
    { //begin真则i++
        n = read(fd, buff+i, 1);//读一个字符
        if(n == 0)//文件末尾
        {
            *(buff+i) = '\0';
            break;
        }
        else if(*(buff+i) == '\r' ||*(buff+i) == '\n')
        {//是回车换行
            if(begin)
            {//为一行
                *(buff+i) = '\0';    
                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 \n");
            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 = '\0';//得到关键字
        while(isspace(*pos))//再次跳过值前面的空格
        {
            pos++;
        }
        value = pos;
        while(!isspace(*pos) && *pos != '\r' && *pos != '\n')//读到结束
        {
            pos++;
        }
        pos = '\0';//得到值
        //根据关键字,将值赋给配置文件的结构
        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*******************\n");
    printf("sHTTPD ListenPort: %d\n",conf_para.ListenPort);
    printf(" MaxClient: %d\n", conf_para.MaxClient);
    printf(" DocumentRoot: %s\n",conf_para.DocumentRoot);
    printf(" DefaultFile:%s\n",conf_para.DefaultFile);
    printf(" CGIRoot:%s \n",conf_para.CGIRoot);
    printf(" DefaultFile:%s\n",conf_para.DefaultFile);
    printf(" TimeOut:%d\n",conf_para.TimeOut);
    printf(" ConfigFile:%s\n",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 ;//返回配置参数
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/522899
推荐阅读
相关标签
  

闽ICP备14008679号