Chinaunix首页 | 论坛 | 博客
  • 博客访问: 63670
  • 博文数量: 21
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 236
  • 用 户 组: 普通用户
  • 注册时间: 2014-09-05 21:34
文章分类

全部博文(21)

文章存档

2015年(21)

我的朋友

分类: LINUX

2015-08-04 15:59:50

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

点击(此处)折叠或打开

  1. //start from the very beginning,and to create greatness
  2. //@author: Chuangwei Lin
  3. //@E-mail:979951191@qq.com
  4. //@brief: 命令行解析代码和配置文件解析的实现

  5. #include "lcw_shttpd.h"

  6. //短选项的配置为c:d:f:h:o:l:m:t:
  7. static char* shortopts="c:d:f:h:o:l:m:t:";
  8. //长选项的配置
  9. //option是getop_long的一个结构体参数p531
  10. static struct option longopts[]=
  11. {
  12.     {"CGIRoot",required_argument,NULL,'c'},
  13.     {"ConfigFile",required_argument,NULL,'f'},
  14.     {"DefaultFile",required_argument,NULL,'d'},
  15.     {"DocumentRoot",required_argument,NULL,'o'},
  16.     {"ListenPort",required_argument,NULL,'l'},
  17.     {"MaxClient",required_argument,NULL,'m'},
  18.     {"TimeOut",required_argument,NULL,'t'},
  19.     {"Help",no_argument,NULL,'h'},
  20.     {0,0,0,0},
  21. }
  22. //初始化时服务器的默认配置
  23. extern struct conf_opts conf_para=
  24. {
  25.     "/usr/local/var/www/cgi-bin/",//CGI根目录
  26.     "index.html",//默认文件名称
  27.     "/usr/local/var/www/",//根文件目录
  28.     "/etc/SHTTPD.conf",//配置文件路径和名称
  29.     8080, //监听端口
  30.     4, //最大客户端数量
  31.     3,//超时时间
  32.     2//初始化线程数量
  33. };
  34. /******************************************************
  35. 函数名:display_usage(void)
  36. 参数:无
  37. 功能:显示参数输入方法
  38. *******************************************************/
  39. void display_usage(void)
  40. {
  41.     printf("*******************Chuangwei Lin*******************\n");
  42.     printf("sHTTPD -l number -m number -o path -c path -d filename -t seconds -o filename\n");
  43.     printf("sHTTPD --ListenPort number\n");
  44.     printf(" --MaxClient number\n");
  45.     printf(" --DocumentRoot) path\n");
  46.     printf(" --DefaultFile) filename\n");
  47.     printf(" --CGIRoot path \n");
  48.     printf(" --DefaultFile filename\n");
  49.     printf(" --TimeOut seconds\n");
  50.     printf(" --ConfigFile filename\n");
  51. }
  52. /******************************************************
  53. 函数名:conf_readline(int fd, char *buff, int len)
  54. 参数:文件描述符,缓冲区,长度
  55. 功能:读取配置文件的一行
  56. *******************************************************/
  57. static int conf_readline(int fd, char *buff, int len)
  58. {
  59.     int n = -1;
  60.     int i = 0;
  61.     int begin = 0;
  62.     memset(buff, 0, len);//清缓冲区
  63.     for(i =0; i<len;begin?i++:i)//当开头部分不为'\r'或者'\n'时i计数
  64.     { //begin真则i++
  65.         n = read(fd, buff+i, 1);//读一个字符
  66.         if(n == 0)//文件末尾
  67.         {
  68.             *(buff+i) = '\0';
  69.             break;
  70.         }
  71.         else if(*(buff+i) == '\r' ||*(buff+i) == '\n')
  72.         {//是回车换行
  73.             if(begin)
  74.             {//为一行
  75.                 *(buff+i) = '\0';    
  76.                 break;
  77.             }
  78.         }
  79.         else
  80.         {
  81.             begin = 1;
  82.         }
  83.     }
  84.     return i;
  85. }

  86. static char* l_opt_arg;//存输入参数
  87. /******************************************************
  88. 函数名:Para_CmdParse(int argc,char* argv[])
  89. 参数:argc:参数个数 ,argv:参数的字符串数组,两个参数一般是从main()函数的输入参数中直接传来
  90. 功能:命令行解析函数,利用getopt_long函数实现
  91. *******************************************************/
  92. static int Para_CmdParse(int argc,char* argv[])
  93. {
  94.     int c;
  95.     int len;
  96.     int value;
  97.     //遍历输入参数,设置配置参数
  98.     while((c=getopt_long(argc,argv,shortopts,longopts,NULL))!=-1)
  99.     {    
  100.         switch(c)    
  101.         { //getopt_long()如果有输入参数,则输入参数为optarg
  102.             case:'c'//CGI跟路径
  103.              l_opt_arg = optarg;
  104.              if (l_opt_arg && l_opt_arg[0] != ':')
  105.              {
  106.                  len = strlen(l_opt_arg);
  107.                  memcpy(conf_para.CGIRoot,l_opt_arg,len+1);//更新
  108.              }
  109.                 break;
  110.             case:'d'//默认文件名称
  111.              l_opt_arg = optarg;
  112.              if (l_opt_arg && l_opt_arg[0] != ':')
  113.              {
  114.                  len = strlen(l_opt_arg);
  115.                  memcpy(conf_para.DefaultFile,l_opt_arg,len+1);
  116.              }
  117.                 break;
  118.             case:'f'//配置文件名称和路径
  119.              l_opt_arg = optarg;
  120.              if (l_opt_arg && l_opt_arg[0] != ':')
  121.              {
  122.                  len = strlen(l_opt_arg);
  123.                  memcpy(conf_para.ConfigFile,l_opt_arg,len+1);
  124.              }
  125.                 break;
  126.             case:'o'//根文件路径
  127.              l_opt_arg = optarg;
  128.              if (l_opt_arg && l_opt_arg[0] != ':')
  129.              {
  130.                  len = strlen(l_opt_arg);
  131.                  memcpy(conf_para.DocumentRoot,l_opt_arg,len+1);
  132.              }
  133.                 break;
  134.             case:'l'//侦听端口
  135.              l_opt_arg = optarg;
  136.              if (l_opt_arg && l_opt_arg[0] != ':')
  137.              {
  138.                  len = strlen(l_opt_arg);
  139.                  value = strtol(l_opt_arg,NULL,10);//转化字符串为整形
  140.                  if (value != LONG_MAX && value != LONG_MIN)
  141.                  {
  142.                      conf_para.ListenPort = value;//更新
  143.                  }
  144.              }
  145.                 break;
  146.             case:'m'//最大客户端数量
  147.              l_opt_arg = optarg;
  148.              if (l_opt_arg && l_opt_arg[0] != ':')
  149.              {
  150.                  len = strlen(l_opt_arg);
  151.                  value = strtol(l_opt_arg,NULL,10);//转化字符串为整形
  152.                  if (value != LONG_MAX && value != LONG_MIN)
  153.                  {
  154.                      conf_para.MaxClient = value;//更新
  155.                  }
  156.              }
  157.                 break;
  158.             case:'t'//超时时间
  159.              l_opt_arg = optarg;
  160.              if (l_opt_arg && l_opt_arg[0] != ':')
  161.              {
  162.                  len = strlen(l_opt_arg);
  163.                  value = strtol(l_opt_arg,NULL,10);//转化字符串为整形
  164.                  if (value != LONG_MAX && value != LONG_MIN)
  165.                  {
  166.                      conf_para.TimeOut = value;//更新
  167.                  }
  168.              }
  169.                 break;
  170.             case:'?'
  171.                 printf("Invalid para \n");
  172.             case:'h'
  173.                 display_usage();
  174.                 break;
  175.         }
  176.     }
  177. }
  178. /******************************************************
  179. 函数名:Para_FileParse(char* file)
  180. 参数:文件
  181. 功能:文件配置解析函数
  182. *******************************************************/
  183. void Para_FileParse(char* file)
  184. {
  185.     #define LINELENGTH 256
  186.     char line[LINELENGTH];//读取缓冲区
  187.     char *name = NULL,*value = NULL;//用于获取关键字和值
  188.     int fd = -1;//文件描述符
  189.     int n = 0;
  190.     fd = open(file,O_RDONLY);//只读方式打开配置文件
  191.     if (-1 == fd)//错误检查
  192.     {
  193.         goto EXITPara_FileParse;//退出
  194.     }
  195.     //命令格式如下
  196.     //[#注释|[空格]关键字[空格]=[空格]value]
  197.     //
  198.     while((n = conf_readline(fd,line,LINELENGTH))!= 0)//每次读取一行
  199.     {
  200.         char *pos = line;//文件位置指针
  201.         while(isspace(*pos))
  202.         {
  203.             pos++;//跳过一行开头部分的空格
  204.         }
  205.         if(*pos == '#')//如果是注释
  206.         {
  207.             continue;//那就读取下一行
  208.         }
  209.         name = pos;//此时的位置就是关键字的开头
  210.         while(!isspace(*pos) && *pos != '=')//不是空格也不是’=‘,则继续读直到读完关键字
  211.         {
  212.             pos++;
  213.         }
  214.         *pos = '\0';//得到关键字
  215.         while(isspace(*pos))//再次跳过值前面的空格
  216.         {
  217.             pos++;
  218.         }
  219.         value = pos;
  220.         while(!isspace(*pos) && *pos != '\r' && *pos != '\n')//读到结束
  221.         {
  222.             pos++;
  223.         }
  224.         pos = '\0';//得到值
  225.         //根据关键字,将值赋给配置文件的结构
  226.         int ivalue;
  227.         if(strncmp("CGIRoot",name,7))
  228.         {
  229.             memcpy(conf_para.CGIRoot,value,strlen(value)+1);
  230.         }
  231.         else if(strncmp("DefaultFile",name,11))
  232.         {
  233.             memcpy(conf_para.DefaultFile,value,strlen(value)+1);
  234.         }
  235.         else if(strncmp("DocumentRoot",name,12))
  236.         {
  237.             memcpy(conf_para.DocumentRoot,value,strlen(value)+1);
  238.         }
  239.         else if(strncmp("ListenPort",name,10))
  240.         {
  241.             ivalue = strtol(value,NULL,10);//转化字符串为整形
  242.             conf_para.ListenPort = ivalue;
  243.         }
  244.         else if(strncmp("MaxClient",name,9))
  245.         {
  246.             ivalue = strtol(value,NULL,10);//转化字符串为整形
  247.             conf_para.MaxClient = ivalue;
  248.         }
  249.         else if(strncmp("TimeOut",name,7))
  250.         {
  251.             ivalue = strtol(value,NULL,10);//转化字符串为整形
  252.             conf_para.TimeOut = ivalue;
  253.         }

  254.     }
  255.     close(fd);//关闭文件
  256. EXITPara_FileParse:
  257.     return ;
  258. }
  259. /******************************************************
  260. 函数名:display_para()
  261. 参数:无
  262. 功能:显示配置的参数
  263. *******************************************************/
  264. static void display_para()
  265. {
  266.     printf("*******************Chuangwei Lin*******************\n");
  267.     printf("sHTTPD ListenPort: %d\n",conf_para.ListenPort);
  268.     printf(" MaxClient: %d\n", conf_para.MaxClient);
  269.     printf(" DocumentRoot: %s\n",conf_para.DocumentRoot);
  270.     printf(" DefaultFile:%s\n",conf_para.DefaultFile);
  271.     printf(" CGIRoot:%s \n",conf_para.CGIRoot);
  272.     printf(" DefaultFile:%s\n",conf_para.DefaultFile);
  273.     printf(" TimeOut:%d\n",conf_para.TimeOut);
  274.     printf(" ConfigFile:%s\n",conf_para.ConfigFile);
  275. }
  276. /******************************************************
  277. 函数名:Para_Init(int argc, char *argv[])
  278. 参数:参数个数,和参数字符串
  279. 功能:初始化配置
  280. *******************************************************/
  281. void Para_Init(int argc, char *argv[])
  282. {
  283.     //解析命令行输入参数
  284.     Para_CmdParse(argc, argv);
  285.     //解析配置文件配置参数
  286.     if(strlen(conf_para.ConfigFile))
  287.      {
  288.          Para_FileParse(conf_para.ConfigFile);
  289.      }
  290.     display_para();
  291.     return ;//返回配置参数
  292. }

阅读(1365) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~