开始学习《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 ;//返回配置参数
}

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

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

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

  2. 一个简单的wed服务器SHTTPD(9)————main函数文件,Makefile,头文件

    主函数: #include "lcw_shttpd.h" //初始化时服务器的默认配置 extern struct conf_opts conf_para= { "/us ...

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

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

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

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

  5. 一个简单的wed服务器SHTTPD(6)———— 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. Tomcat剖析(一):一个简单的Web服务器

    Tomcat剖析(一):一个简单的Web服务器 1. Tomcat剖析(一):一个简单的Web服务器 2. Tomcat剖析(二):一个简单的Servlet服务器 3. Tomcat剖析(三):连接器 ...

随机推荐

  1. 二、Centos7—U盘启动盘制作

      1,准备一个8gU盘. 2.iso系统镜像文件. 3.下载UltraISO软件制作启动盘. 4.运行UltraISO软件 5.在UltraISO软件中打开刚下载的Centos系统安装文件 6.开始 ...

  2. python3(二十三)classInstance

    """ 类和实例和访问权限 """ __author__ = 'shaozhiqi' # class后面紧接着是类名,即Student,类名 ...

  3. hadoop(七)集群配置同步(hadoop完全分布式四)|9

    前置配置:rsync远程同步|xsync集群分发(hadoop完全分布式准备三)|9 1. 分布式集群分配原则 部署分配原则 说明Namenode和secondarynamenode占用内存较大,建议 ...

  4. lr具体使用步骤概述

    lr具体使用 1 无工具情况下的性能测试 2性能测试工具LoadRunner的工作原理 3 VuGen应用介绍 4 协议的类型及选择方法 5 脚本的创建过程 6 脚本的参数化 7 调试技术 8 Con ...

  5. mysql添加,授权,删除用户以及连接数据库Can't connect to MySQL server on '192.168.31.106' (113)错误排查

    centos7下面操作mysql添加,授权,删除用户 添加用户 以root用户登录数据库,运行以下命令: create user test identified by '; 上面创建了用户test,密 ...

  6. csdn的垃圾体验

    微信扫码登录网页csdn,每次扫码都是csdn有关的不同的公众号,必须关注才可以登录,为了推广公众号真是简直了 无法修改id 注销也需要扫码,这次是必须下载csdn的app才能注销,我真是服了,我都要 ...

  7. golang实现常用集合原理介绍

    golang本身对常用集合的封装还是比较少的,主要有数组(切片).双向链表.堆等.在工作中可能用到其他常用的集合,于是我自己对常用的集合进行了封装,并对原理做了简单介绍,代码库地址:https://g ...

  8. 后端code review finished 12-28

    今天只有天赋和士杰有相应的后端代码的code review工作,因为并没有召开daily scrum.只是天赋和士杰对后端所有的代码进行了review,对代码进行了整理并删除了一些残留的0 refre ...

  9. PHP函数:json_last_error

    json_last_error()  - 返回 JSON 编码解码时最后发生的错误.. 说明: json_last_error ( void ) : int 参数: 无 返回值: 返回一个整型(int ...

  10. [linux][nginx] 常用

    原文链接http://www.cnblogs.com/codingcloud/p/5095066.html 启动 启动代码格式:nginx安装目录地址 -c nginx配置文件地址 例如: [root ...