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

上一次对字符串工具模块进行了封装,这次主要是对"参数配置模块"的封装,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. MultiDesk远程桌面连接

    MultiDesk 是一个选项卡(TAB标签)方式的远程桌面连接 (Terminal Services Client),可以管理组远程桌面连接,更改连接端口. 功能特性 绿色软件,只有一个很小的可执行 ...

  2. picard报错

    /home/yueyao/bio/anaconda2/bin/java -jar /home/yueyao/bio/anaconda2/share/picard-2.14.1-0/picard.jar ...

  3. LeetCode 637. 二叉树的层平均值(Average of Levels in Binary Tree)

    637. 二叉树的层平均值 637. Average of Levels in Binary Tree LeetCode637. Average of Levels in Binary Tree 题目 ...

  4. 哈希--Hash,“散列”/“哈希”

    哈希 Hash,翻译“散列”,音译为“哈希”,把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是散列值的空间通常远小于输入的空间,不同的输入可能会散 ...

  5. [转帖]AMD:Zen 2霄龙处理器每美元性能可达英特尔至强5.6倍

    AMD:Zen 2霄龙处理器每美元性能可达英特尔至强5.6倍 2019-10-20 6:35:38来源:IT之家作者:孤城责编:孤城评论:32 https://www.ithome.com/0/451 ...

  6. python数据库基础

    1.数据类型:(使用原则:够用就行,尽量使用范围小的) 整数:int,bit 小数:decimal 字符串:varchar(可变长度),char(固定长度字符串) 日期时间:date,time,dat ...

  7. 米联客 osrc_virtual_machine_sdx2017_4 虚拟机的使用

    今天大部分时间都在高csdn的博客的,一直无法和word关联,来不及写使用教程了,先发下载链接. 虚拟机安装的是ubuntu16.4.3,vivado软件是SDX2017.4版本,包括的vivado2 ...

  8. shiro是什么?

    是什么? Shiro是一个非常强大的.易于使用的.开源的.权限框架.它包括了权限校验.权限授予.会话管理.安全加密等组件. 为什么要使用shiro? 如果你是需要设计RBAC(Role Based A ...

  9. Codeforces Round #419 (Div. 1) (ABCD)

    1. 815A Karen and Game 大意: 给定$nm$矩阵, 每次选择一行或一列全部减$1$, 求最少次数使得矩阵全$0$ 贪心, $n>m$时每次取一列, 否则取一行 #inclu ...

  10. App功能测试点总结

    1.手机操作系统android(谷歌).ios(苹果).Windows phone(微软).Symbian(诺基亚).BlackBerry OS(黑莓).windows mobile(微软),目前主流 ...