开始学习《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. C语言输出菱形

    #include<stdio.h> #include<string.h> int main(){          int data[7][7] = {0};     for( ...

  2. 数据结构和算法(Golang实现)(21)排序算法-插入排序

    插入排序 插入排序,一般我们指的是简单插入排序,也可以叫直接插入排序.就是说,每次把一个数插到已经排好序的数列里面形成新的排好序的数列,以此反复. 插入排序属于插入类排序算法. 除了我以外,有些人打扑 ...

  3. 360众测考试,weblogic题(CVE-2018-2894)文件上传漏洞

    0x01 漏洞简介 Weblogic管理端未授权的两个页面存在任意上传jsp文件漏洞,进而获取服务器权限. Oracle 7月更新中,修复了Weblogic Web Service Test Page ...

  4. 【翻译】Java Array的排名前十方法(Top 10 Methods for Java Arrays)

    这里列举了Java Array 的前十的方法.他们在stackoverflow最大投票的问题. The following are top 10 methods for Java Array. The ...

  5. ModuleNotFoundError: No module named 'sklearn.cross_validation'

    本文为CSDN博主「不服输的南瓜」的原创文章,遵循 CC 4.0 BY-SA 版权协议 原文链接 ModuleNotFoundError: No module named 'sklearn.cross ...

  6. 基于thinkphp3.2.3开发的CMS内容管理系统 - ThinkPHP框架

    基于thinkphp3.2.3开发的CMS内容管理系统 thinkphp版本:3.2.3 功能: --分类栏目管理 --文章管理 --用户管理 --友情链接管理 --系统设置 目前占时这些功能,更多功 ...

  7. 【题解】P3959 宝藏 - 状压dp / dfs剪枝

    P3959 宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的m  条道路和它们的长度. 小明决心亲自前往挖掘所有宝 ...

  8. Java8新特性(1):Lambda表达式

    Lambda表达式可以理解为一种匿名函数:没有名称,但有参数列表.函数主体.返回类型.它是行为参数化的一种实现,行为参数化是指将不同的行为作为参数传递给方法,方法的所具备的能力取决于它接收的行为参数. ...

  9. 统计字符串中每种字符出现的评率(HashMap中getOrDefault(K, V)方法的使用)

    为了统计字符串中每种字符出现的频率,使用HashMap这种数据结构.其中,字符作为Key,出现的频率作为Value. 基本算法为: 1. 将字符串分成字符数组 2. (1)如果HashMap中的Key ...

  10. java 脚本引擎执行js

    为用到时,使用方便直接保存一下代码 package com.xzlf.reflectTest; import java.io.BufferedReader; import java.io.FileIn ...