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

上一次对字符串工具模块进行了封装,这次主要是对"参数配置模块"的封装,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. ubuntu 18.04 安装搜狗输入法

    安装 fcitxsudo apt install fcitx 配置输入法打开fcitx配置界面,点击桌面左下角的菜单,弹出如下桌面: 点击: “Input Method”,进入设置界面 点击 “OK” ...

  2. windows强大的快捷键

    1 电脑锁屏 有些时候,需要暂时离开座位去处理其他事,可是电脑还有数据再跑. 关掉的话,数据就白跑了,不关的话,又不想让别人看到我电脑的资料. 那么就按住windows键后,再按L键. 这样电脑就直接 ...

  3. 软件素材---C语言函数不确定个数的入参的处理

    1 :  #用来把参数转换成字符串 #define P(A) printf("%s:%d\n",#A,A);int main(int argc, char **argv) {    ...

  4. Rust零碎总结

    1.Rust里没有null的概念,但是实际上有很多地方是需要null的概念的,这个时候就可以用Option来代替,它是泛型T的一个包装类,就是C#里的int?或Java里的Optional: [但反序 ...

  5. 用jquery和php实现ajax异步请求响应

    ajax技术可以实现异步请求和响应,下面的是用jquery向一个php脚本发送异步请求,并得到响应. 第一步,准备好前台的html表单,和jquery实现的ajax请求 <html lang=& ...

  6. ~postman全局变量与环境变量介绍

    postman官方文档:https://learning.getpostman.com/docs/postman/scripts/test_examples/ 一.环境变量 实例:将URL作为环境变量 ...

  7. Go语言学习笔记(8)——包和结构体

    包 —— 每个可执行的应用程序必须包含一个主函数,它是执行的入口点.主函数应该存在main包中. 结构体: 通过 . 操作符访问结构体的各个成员! 1. 定义结构体类型person: type per ...

  8. netty--使用注意事项

  9. 数据库中间件之mycat读写分离

    mycat核心概念 逻辑库 mycat中定义.管理的数据库 逻辑表 逻辑库中包含的需分库分表存储的表 datanode 数据节点(分片节点),逻辑表分片的存放节点 datahost 数据主机(节点主机 ...

  10. C# DataGridView 动态添加列和行

    https://blog.csdn.net/alisa525/article/details/7350471 dataGridView1.ReadOnly = true ;      //禁用编辑功能 ...