间隔了一周时间没写了,由于今年的股势行情貌似不错的样子,对于对股市完全不懂的我也在蠢蠢欲动,所以最近一周业余时间在“不务正业”-----学习炒股。发现学习它其实挺费神的,满脑子都是走势图,而且是神经有点受刺激的感觉,发现这个坚决不能在上班时间去想这事,不然会非常影响情绪,毕境对于普通老百姓来讲经济来源还主要是来源于工作,专职炒股也不适合像我这样笨拙的人,不过可以业余有时间学习学习,入市那还是得非常非常谨慎,所以放下它,接着来学习技术这才是王道,言归正传。

上一次对字符串工具模块进行了封装,这次主要是对"参数配置模块"的封装,FTP中有很多配置相关的选项,不可能硬编码到代码中,而应该将它们配置到配置文件当中,像vsftpd的配置文件如下:

而对于miniftpd所有的参数配置项如下:

对于上面这些变量应该是与对应的配置项进行一一对应的,所以需要定义三张表格来进行一一对应:

配置文件中的配置项与配置项变量对应关系表

static struct parseconf_bool_setting

{

const char *p_setting_name;

int *p_variable;

}

parseconf_bool_array[] =

{

{ "pasv_enable", &tunable_pasv_enable },

{ "port_enable", &tunable_port_enable },

{ NULL, NULL }

};

static struct parseconf_uint_setting

{

const char *p_setting_name;

unsigned int *p_variable;

}

parseconf_uint_array[] =

{

{ "listen_port", &tunable_listen_port },

{ "max_clients", &tunable_max_clients },

{ "max_per_ip", &tunable_max_per_ip },

{ "accept_timeout", &tunable_accept_timeout },

{ "connect_timeout", &tunable_connect_timeout },

{ "idle_session_timeout", &tunable_idle_session_timeout },

{ "data_connection_timeout", &tunable_data_connection_timeout },

{ "local_umask", &tunable_local_umask },

{ "upload_max_rate", &tunable_upload_max_rate },

{ "download_max_rate", &tunable_download_max_rate },

{ NULL, NULL }

};

static struct parseconf_str_setting

{

const char *p_setting_name;

const char **p_variable;

}

parseconf_str_array[] =

{

{ "listen_address", &tunable_listen_address },

{ NULL, NULL }//最后这个NULL是为了遍历用的

};

下面定义两个操作配置文件的函数:

函数

说明

void parseconf_load_file(const char *path);

加载配置文件

void parseconf_load_setting(const char *setting);

将配置项加载到相应的变量

下面则开始进行编码,首先先新建配置文件模块文:

tunable.h:对其变量进行声明:

#ifndef _TUNABLE_H_
#define _TUNABLE_H_ extern int tunable_pasv_enable;
extern int tunable_port_enable;
extern unsigned int tunable_listen_port;
extern unsigned int tunable_max_clients;
extern unsigned int tunable_max_per_ip;
extern unsigned int tunable_accept_timeout;
extern unsigned int tunable_connect_timeout;
extern unsigned int tunable_idle_session_timeout;
extern unsigned int tunable_data_connection_timeout;
extern unsigned int tunable_local_umask;
extern unsigned int tunable_upload_max_rate;
extern unsigned int tunable_download_max_rate;
extern const char *tunable_listen_address; #endif /* _TUNABLE_H_ */

tunable.h:

#include "tunable.h"

int tunable_pasv_enable = ;
int tunable_port_enable = ;
unsigned int tunable_listen_port = ;
unsigned int tunable_max_clients = ;
unsigned int tunable_max_per_ip = ;
unsigned int tunable_accept_timeout = ;
unsigned int tunable_connect_timeout = ;
unsigned int tunable_idle_session_timeout = ;
unsigned int tunable_data_connection_timeout = ;
unsigned int tunable_local_umask = ;
unsigned int tunable_upload_max_rate = ;
unsigned int tunable_download_max_rate = ;
const char *tunable_listen_address;

另外新建一个配置文件:

接下来还要暴露两个接口出来,对文件和配置项的解析:

函数

说明

void parseconf_load_file(const char *path);

加载配置文件

void parseconf_load_setting(const char *setting);

将配置项加载到相应的变量

新建一个解析模块来做上面的解析工作:

parseconf.h:

#ifndef _PARSE_CONF_H_
#define _PARSE_CONF_H_ void parseconf_load_file(const char *path);
void parseconf_load_setting(const char *setting); #endif /* _PARSE_CONF_H_ */

parseconf.c:

#include "parseconf.h"
#include "common.h"
#include "tunable.h" void parseconf_load_file(const char *path){ } void parseconf_load_setting(const char *setting){ }

下面来实现这两个函数:

另外,由于fgets函数读取的一行字符包含'\n',所以需要将其去掉,可以用我们之前封装的现成方法:

接下来实现命令行的解析函数,在正式解析之前,需要将配置文件中的配置项与配置项变量对应关系表用代码定义出来,如下:

#include "parseconf.h"
#include "common.h"
#include "tunable.h" static struct parseconf_bool_setting
{
const char *p_setting_name;
int *p_variable;
}
parseconf_bool_array[] =
{
{ "pasv_enable", &tunable_pasv_enable },
{ "port_enable", &tunable_port_enable },
{ NULL, NULL }
}; static struct parseconf_uint_setting
{
const char *p_setting_name;
unsigned int *p_variable;
}
parseconf_uint_array[] =
{
{ "listen_port", &tunable_listen_port },
{ "max_clients", &tunable_max_clients },
{ "max_per_ip", &tunable_max_per_ip },
{ "accept_timeout", &tunable_accept_timeout },
{ "connect_timeout", &tunable_connect_timeout },
{ "idle_session_timeout", &tunable_idle_session_timeout },
{ "data_connection_timeout", &tunable_data_connection_timeout },
{ "local_umask", &tunable_local_umask },
{ "upload_max_rate", &tunable_upload_max_rate },
{ "download_max_rate", &tunable_download_max_rate },
{ NULL, NULL }
}; static struct parseconf_str_setting
{
const char *p_setting_name;
const char **p_variable;
}
parseconf_str_array[] =
{
{ "listen_address", &tunable_listen_address },
{ NULL, NULL }
}; void parseconf_load_file(const char *path){
FILE *fp = fopen(path, "r");
if (fp == NULL)
ERR_EXIT("fopen"); char setting_line[] = {};
while (fgets(setting_line, sizeof(setting_line), fp) != NULL)
{
if (strlen(setting_line) ==
|| setting_line[] == '#'
|| str_all_space(setting_line))
continue; str_trim_crlf(setting_line);
parseconf_load_setting(setting_line);
memset(setting_line, , sizeof(setting_line));
} fclose(fp);
} void parseconf_load_setting(const char *setting){ }

其中各个变量是来自于全局变量tunable.c中。

可见有三种类型的参数,下面一个个来进行解析,对于"pasv_enable=YES"一个配置,可能会写成“    pasv_enable=YES”,所以先去掉左控格:

然后需要将key=pasv_enable;value=YES分隔开,这里可以用之前封装的现成的命令:

但也有可能用户没有配置value,如“pasv_enable=”,所以这是不合法的,也应该做下判断:

接下来,就需要拿这个key在上面的配置表格变量中进行搜索,如果找到了,则将其值赋值给该配置变量,如下:

如果说没有找到话,也就说明当前的配置项不是字符串类型的,这时,还得继续去其它类型的配置项中进行搜寻,如下:

而对于布尔类型,可以有以下几种形式:

AA=YES

AA=yes

AA=TRUE

AA=1

所以,首先将value统一成大写:

当遍历boolean类型配置项中也没有找到时,则需要在无符号整形中进行查找,其中无符号整形有两种形式:一种八进制,以0开头,比如"local_umask=077";另一种是十进制,如:"listen_port=21",所以需要做下判断,代码基本类似:

下面则来编译运行一下,在编译运行之前,需要把新加的模块加入到Makefile中:

上面看已经正常通过了,那还是看不出这些配置信息是否正常读取了,所以下面需要写一个测试程序来检验一下:

编译运行:

再次编译运行:

接下来可以应用某些配置项了:

编译运行:

用FTP客户端连接:

可见这样代码就变成可配置的了,另外配置文件的文件名可以做成宏:

加载时直接用该宏:

好了,经过几周的耽搁先完成到这,之后会慢慢恢复学习。

Linux网络编程综合运用之MiniFtp实现(六)的更多相关文章

  1. Linux网络编程综合运用之MiniFtp实现(一)

    春节过后,万物复苏,在这元宵佳节的前一天,决定继续开启新年的学习计划,生命在于运动,提高源于学习,在经过漫长的Linux网络编程学习后,接下来会以一个综合的小项目来将所学的知识点综合运用,首先是对项目 ...

  2. Linux网络编程综合运用之MiniFtp实现(四)

    从今天开始,正式进入MiniFtp的代码编写阶段了,好兴奋,接下来很长一段时间会将整个实现过程从无到有一点点实现出来,达到综合应用的效果,话不多说正入正题: 这节主要是将基础代码框架搭建好,基于上节介 ...

  3. Linux网络编程综合运用之MiniFtp实现(九)

    上次中实现了FTP命令的映射来避免很多if....else的判断,这次主要是开始实现目录列表的传输,先看一下目前实现的: 数据连接创建好之后则开始进行目录列表的传输了,而要传输目录列表,首先要将目录列 ...

  4. Linux网络编程综合运用之MiniFtp实现(五)

    转眼兴奋的五一小长假就要到来了,在放假前夕还是需要保持一颗淡定的心,上次中已经对miniFTP有基础框架进行了搭建,这次继续进行往上加代码,这次主要还是将经历投射到handle_child()服务进程 ...

  5. Linux网络编程综合运用之MiniFtp实现(八)

    上节中实现了"USER"和"PASS"命令,如下: 事实上FTP是有很多命令组成的,如果就采用上面的这种方法来实现的话,就会有很多if...else if语句, ...

  6. Linux网络编程综合运用之MiniFtp实现(七)

    上节中实现了配置文件的解析,这节来实现用户登录的验证,首先用客户端来登录vsftpd来演示登录的过程: 接着再连接miniftpd,来看下目前的效果: 接下来实现它,与协议相关的模块都是在ftppro ...

  7. Linux网络编程综合运用之MiniFtp实现(三)

    前面已经对FTP相关的一些概念有了基本的认识,接下来就要进入代码编写阶段了,也是非常兴奋的阶段,在开启这个它之前先对项目需求进行一个梳理,对其我们要实现的FTP服务器是一个什么样子. ftp命令列表 ...

  8. 【深入浅出Linux网络编程】 "开篇 -- 知其然,知其所以然"

    [深入浅出Linux网络编程]是一个连载博客,内容源于本人的工作经验,旨在给读者提供靠谱高效的学习途径,不必在零散的互联网资源中浪费精力,快速的掌握Linux网络编程. 连载包含4篇,会陆续编写发出, ...

  9. 【linux草鞋应用编程系列】_5_ Linux网络编程

    一.网络通信简介   第一部分内容,暂时没法描述,内容实在太多,待后续专门的系列文章.   二.linux网络通信     在linux中继承了Unix下“一切皆文件”的思想, 在linux中要实现网 ...

随机推荐

  1. web端自动化——selenium3+Python3+pycharm自动化

    1.前言: 对于初学者来说,python自带的IDLE,精简又方便,不过一个好的编辑器能让python编码变得更方便,更加优美些. 不过呢,也可以自己去下载其他更好用的代码编辑器,在这推荐: PyCh ...

  2. Cannot assign requested address的解决办法

    今天想试一下redis,写了个程序,对redis连续进行100000访问,却出现以了Cannot assign requested address的问题,我起先是以为是redis的问题(可能承受不了这 ...

  3. models模型层

    ORM简介 查询数据层次图解:如果操作mysql,ORM是在pymysq之上又进行了一层封装 MVC或者MTV框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需 ...

  4. [转帖]LINUX下使用rinetd端口转发

    LINUX下使用rinetd端口转发 https://www.iteye.com/blog/lvinie-1167701 . 本来想自己写一下 发现没必要. 并且原作者提供了pan.baidu.com ...

  5. linux 磁盘占用的排查流程

    Linux 服务器在使用过程中可能会遇到各种问题,其中之一就是"没有可用空间". 遇到这种情况,就需要进行排查,定位到消耗了磁盘的那个文件夹. 流程如下: 1. df -h df ...

  6. THUPC2019/CTS2019/APIO2019/PKUSC2019游记

    THUPC2019/CTS2019/APIO2019/PKUSC2019游记 5.10 中铺,火车好晃啊 5.11 打了THUPC2019的练习赛,华容道好评(四个小兵,杠鸭!) 5.12 打了THU ...

  7. idea 控制台 彩色打印日志

    IDEA右上角:Edit Configurations,点击,找到VM options,填入-Dspring.output.ansi.enabled=ALWAYS. 重新启动应用,就会发现控制台日志变 ...

  8. 洛谷 P1217 回文质数

    洛谷 P1217 回文质数 链接 https://www.luogu.org/problem/P1217 题目 题目描述 因为 151 既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 ...

  9. MySQL绿色版mysql-5.7.17-winx64简洁安装教程

    1.解压MySQL绿色版,复制my-default.ini,修改名称为my.ini 2. 以下为my.ini文件 # For advice on how to change settings plea ...

  10. C# 用Redis实现的分布式锁

    Redis实现分布式锁(悲观锁/乐观锁) 对锁的概念和应用场景在此就不阐述了,网上搜索有很多解释,只是我搜索到的使用C#利用Redis的SetNX命令实现的锁虽然能用,但是都不太适合我需要的场景. 基 ...