zoukankan      html  css  js  c++  java
  • ftp server来源分析20140602

    ftp  server学习位和源代码分析片
    记录自己的第一个开源的分析过程:
    从源代码:野狐灯(我接下来的几篇文章是从源头:野狐灯,每个以下哪项不是他们设置。)


    20140602


    Ftp的源码目录例如以下
    dxyh.h     dxyh_lib.c            包裹函数(经常使用的) 
    dxyh_thread.h  dxyh_thread_lib.c   线程包裹函数
    Ftpd.h   ftpd.c                  主代码 
    ftpd_main.c                      程序入口
    error.h   error.c                  错误处理的函数
    record.h      record.c            生成相关的记录
    Makefile                        makefile文件
    readme   自己加入的改动的记录
    首先是把每一个文件大致浏览了一下知道大概的过程
    从ftpd_main.c開始分析之旅
    //ftpd_main.c
      2 #include <stdio.h>
      3 #include "ftpd.h"
      4 #include "record.h"
      5 #include "error.h"
      6 #include "dxyh.h"
      7 
      8 int main(int argc, char **argv)
      9 {
     10         int listenfd;
     11 
     12         ftpd_init();
     13         ftpd_parse_args(argc, argv);
     14         listenfd = ftpd_create_serv();
     15         ftpd_do_loop(listenfd);
     16         return 0;
     17 }
     18 
    在ftpd.c 中大概看了一下 ftpd_init();感觉没什么
    再看ftpd_parse_args(argc,argv)
    感觉内容挺多的,
    先看了一下以下这个函数
    getopt_long()


    #include <getopt.h>
    2函数原型
    编辑


    int getopt_long(int argc, char * const argv[],
    const char *optstring,
    const struct option *longopts, int *longindex);
    3函数说明
    编辑


    getopt被用来解析命令行选项參数。
    getopt_long支持长选项的命令行解析,使用man getopt_long,得到其声明例如以下:
    int getopt_long(int argc, char * const argv[],const char *optstring, const struct option *longopts,int *longindex);
    函数中的argc和argv通常直接从main()的两个參数传递而来。

    optsting是选项參数组成的字符串:
    字符串optstring能够下列元素:
    1.单个字符,表示选项,
    2.单个字符后接一个冒号:表示该选项后必须跟一个參数。參数紧跟在选项后或者以空格隔开。

    该參数的指针赋给optarg。


    3 单个字符后跟两个冒号,表示该选项后能够有參数也能够没有參数。

    假设有參数。參数必须紧跟在选项后不能以空格隔开。该參数的指针赋给optarg。

    (这个特性是GNU的扩张)。
    optstring是一个字符串,表示能够接受的參数。比如,"a:b:cd"。表示能够接受的參数是a,b,c,d,当中,a和b參数后面跟有很多其它的參数值。(比如:-a host -b name)
    參数longopts,事实上是一个结构的实例:
    struct option {
    const char *name; //name表示的是长參数名
    int has_arg; //has_arg有3个值,no_argument(或者是0),表示该參数后面不跟參数值
    // required_argument(或者是1),表示该參数后面一定要跟个參数值
    // optional_argument(或者是2),表示该參数后面能够跟。也能够不跟參数值
    int *flag;
    //用来决定。getopt_long()的返回值究竟是什么。

    假设flag是null(通常情况),则函数会返回与该项option匹配的val值;假设flag不是NULL。则将val值赋予flag所指向的内存。而且返回值设置为0。
    int val; //和flag联合决定返回值
    }
    參数longindex,表示当前长參数在longopts中的索引值。[1]
    给个样例:
    struct option long_options[] = {
    {"a123", required_argument, 0, 'a'},
    {"c123", no_argument, 0, 'c'},
    }
    如今,假设命令行的參数是-a 123,那么调用getopt_long()将返回字符'a',而且将字符串123由optarg返回(注意注意!字符串123由optarg带回!

    optarg不须要定义,在getopt.h中已经有定义),那么。假设命令行參数是-c。那么调用getopt_long()将返回字符'c',而此时,optarg是null。

    最后。当getopt_long()将命令行所有參数所有解析完毕后。返回-1。


    4注意
    编辑


    required_argument(或者是1)时。參数输入格式为:--參数 值 或者 --參数=值。
    optional_argument(或者是2)时,參数输入格式仅仅能为:--參数=值。
    5范例
    编辑


    #include <stdio.h>
    #include <getopt.h>
    char *l_opt_arg;
    char* const short_options = "nbl:";
    struct option long_options[] = {
    { "name", 0, NULL, 'n' },
    { "bf_name", 0, NULL, 'b' },
    { "love", 1, NULL, 'l' },
    { 0, 0, 0, 0},
    };
    int main(int argc, char *argv[])
    {
    int c;
    while((c = getopt_long (argc, argv, short_options, long_options, NULL)) != -1)
    {
    switch (c)
    {
    case 'n':
    printf("My name is XL. ");
    break;
    case 'b':
    printf("His name is ST. ");
    break;
    case 'l':
    l_opt_arg = optarg;
    printf("Our love is %s! ", l_opt_arg);
    break;
    }
    }
    return 0;
    }
    [root@localhost wyp]# gcc -o getopt getopt.c
    [root@localhost wyp]# ./getopt -n -b -l forever
    My name is XL.
    His name is ST.
    Our love is forever!
    [root@localhost liuxltest]#
    [root@localhost liuxltest]# ./getopt -nb -l forever
    My name is XL.
    His name is ST.
    Our love is forever!
    [root@localhost liuxltest]# ./getopt -nbl forever
    My name is XL.
    His name is ST.
    Our love is forever!


    看到有err_msg()这个函数
    在error.c 中找到这个函数
    又查找va_list 的使用方法


    va_list


    VA_LIST 是在C语言中解决变參问题的一组宏,所在头文件:#include <stdarg.h>
    #ifdef _M_ALPHA
    typedef struct {
    char *a0; /* pointer to first homed integer argument */
    int offset; /* byte offset of next parameter */
    } va_list;
    #else
    typedef char * va_list;
    #endif
    _M_ALPHA是指DEC ALPHA(Alpha AXP)架构。

    所以普通情况下va_list所定义变量为字符[1]指针。





    INTSIZEOF 宏,获取类型占用的空间长度,最小占用长度为int的整数倍:
    #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )


    ~是位取反的意思。
    _INTSIZEOF(n)整个做的事情就是将n的长度化为int长度的整数倍。
    比方n为5。二进制就是101b,int长度为4,二进制为100b,那么n化为int长度的整数倍就应该为8。
    ~(sizeof(int) - 1) )就应该为~(4-1)=~(00000011b)=11111100b。这样不论什么数& ~(sizeof(int) - 1) )后最后两位肯定为0,就肯定是4的整数倍了。
    (sizeof(n) + sizeof(int) - 1)就是将大于4m但小于等于4(m+1)的数提高到大于等于4(m+1)但小于4(m+2)。这样再& ~(sizeof(int) - 1) )后就正好将原长度补齐到4的倍数了。




    VA_START宏。获取可变參数列表的第一个參数的地址(ap是类型为va_list的指针,v是可变參数最右边的參数):
    #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
    VA_ARG宏,获取可变參数的当前參数,返回指定类型并将指针指向下一參数(t參数描写叙述了当前參数的类型):
    #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
    VA_END宏。清空va_list可变參数列表:
    #define va_end(ap) ( ap = (va_list)0 )
    3使用方法
    编辑


    (1)首先在函数里定义一具VA_LIST型的变量。这个变量是指向參数的指针。
    (2)然后用VA_START宏初始化刚定义的VA_LIST变量;
    (3)然后用VA_ARG返回可变的參数,VA_ARG的第二个參数是你要返回的參数的类型(假设函数有多个可变參数的。依次调用VA_ARG获取各个參数);
    (4)最后用VA_END宏结束可变參数的获取。
    4注意问题
    编辑


    (1)可变參数的类型和个数全然由程订购代码控制,它不智能识别不同参数的数量和类型;
    (2)假设我们并不需要每个参数一一详细解释。仅需要被复制到缓冲器变量列表,可用的vsprintf功能;
    (3)由于编译器检查的函数原型可变参数不够严谨格,故障排除不利的编程.它并不能帮助我们写出高质量的代码;


    感觉很多东西,快来硬着头皮继续往下看!

  • 相关阅读:
    hihoCoder #1062 : 最近公共祖先·一
    hihoCoder #1050 : 树中的最长路
    hihoCoder #1049 : 后序遍历
    108 Convert Sorted Array to Binary Search Tree 将有序数组转换为二叉搜索树
    107 Binary Tree Level Order Traversal II 二叉树的层次遍历 II
    106 Construct Binary Tree from Inorder and Postorder Traversal 从中序与后序遍历序列构造二叉树
    105 Construct Binary Tree from Preorder and Inorder Traversal 从前序与中序遍历序列构造二叉树
    104 Maximum Depth of Binary Tree 二叉树的最大深度
    102 Binary Tree Level Order Traversal 二叉树的层次遍历
    101 Symmetric Tree 判断一颗二叉树是否是镜像二叉树
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4602145.html
Copyright © 2011-2022 走看看