最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

Mongoose源码剖析:数据结构篇

来源:动视网 责编:小OO 时间:2025-09-26 04:21:03
文档

Mongoose源码剖析:数据结构篇

Mongoose源码剖析:数据结构篇作者:吴秦出处:http://www.cnblogs.com/skynet/本文基于署名2.5中国许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接).引言Mongoose中有几个数据结构扮演着重要的角色,它们分别是:•structmg_context:保存Mongoose的上下文,几乎每个函数都有mg_context参数•structmg_connection:保存HTPP连接信息•structmg_request_inf
推荐度:
导读Mongoose源码剖析:数据结构篇作者:吴秦出处:http://www.cnblogs.com/skynet/本文基于署名2.5中国许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接).引言Mongoose中有几个数据结构扮演着重要的角色,它们分别是:•structmg_context:保存Mongoose的上下文,几乎每个函数都有mg_context参数•structmg_connection:保存HTPP连接信息•structmg_request_inf
Mongoose源码剖析:数据结构篇

作者:吴秦

出处:http://www.cnblogs.com/skynet/

本文基于署名 2.5 中国许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接).

引言

Mongoose中有几个数据结构扮演着重要的角色,它们分别是:

•    struct mg_context:保存Mongoose的上下文,几乎每个函数都有mg_context参数 

•    struct mg_connection:保存HTPP连接信息 

•    struct mg_request_info:保存HTTP请求的信息,这个结构体传递给URL处理函数

 

我之所以现在这里介绍它,因为之后的分析工作中要用到它们,如果在读完本文后还不能很好的理解,请将问题带到后续文章中或代码分析中去,你会找到答案的。下面分别介绍它们。本文的主要内容如下:

•    1、mg_context详解 

•    2、mg_connection详解 

•    3、mg_request_info详解 

•    4、其他数据结构 

•    5、总结

1、mg_context详解

mg_context结构体——表示Mongoose的上下文,也称为一个实例句柄。它的成员如下:

struct mg_context {

    int        stop_flag;    /* Should we stop event loop    */

    SSL_CTX        *ssl_ctx;    /* SSL context            */

    FILE        *access_log;    /* Opened access log        */

    FILE        *error_log;    /* Opened error log        */

    struct socket    listeners[MAX_LISTENING_SOCKETS];

    int        num_listeners;

    struct callback    callbacks[MAX_CALLBACKS];

    int        num_callbacks;

    char        *options[NUM_OPTIONS];    /* Configured opions    */

    pthread_mutex_t    opt_mutex[NUM_OPTIONS];    /* Option protector    */

    int        max_threads;    /* Maximum number of threads    */

    int        num_threads;    /* Number of threads        */

    int        num_idle;    /* Number of idle threads    */

    pthread_mutex_t    thr_mutex;    /* Protects (max|num)_threads    */

    pthread_cond_t    thr_cond;

    pthread_mutex_t    bind_mutex;    /* Protects bind operations    */

    struct socket    queue[20];    /* Accepted sockets        */

    int        sq_head;    /* Head of the socket queue    */

    int        sq_tail;    /* Tail of the socket queue    */

    pthread_cond_t    empty_cond;    /* Socket queue empty condvar    */

    pthread_cond_t    full_cond;    /* Socket queue full condvar    */

    mg_spcb_t    ssl_password_callback;

    mg_callback_t    log_callback;

};

这个结构体在mg_start()中创建和初始化,其它函数大部分都会用它。因此mg_start()应该首先被调用。它非常重要,几乎所有的函数都要用到它。

1)、stop_flag表示是否应该停止的标记,它有三个可能的值0、1、2。 stop_flag=0表示 不应该停止,这是初始值;stop_flag=1表示停止,在mg_stop()函数中的一开始设置stop_flag=1,这会触发mg_fini(),且在mg_stop()中会一直等待mg_fini执行完成;stop_flag=2用于通知mg_stop(),mg_fini已经执行完成,stop_flag=2在mg_fini函数中的末尾设置。

2)、ssl_ctx是结构体ssl_ctx_st的实例,它来自OpenSSL开源项目,作者把它放到这里的原因是使其于OpenSSL的源码安装,这样只有系统上面安装有SSL库,mongoose+SSL就能编译通过。

3)、access_log、error_log很明显是指向访问日志文件、错误日志文件。

4)、listeners数组存储mongoose建立的多个web server,每个web server都是listeners数组中的一个元素。例如,一个服务器可以分别在端口8080、8888建立web server,这样8080端口的那个server是listerns数组中的一个元素,8888端口的那个server也是listeners数组中的一个元素。换句话说,listeners数组表示web server的socket地址。num_listeners表示listeners数组的元素个数。

5)、callbacks是结构体callback的数组,而callback本身是一个结构体,包含几个回调句柄。num_callbacks是callbacks数组元素的个数。 

6)、options数组,是用于存储配置选项的,例如端口号、工作目录等等。opt_mutext对配置进行操作的互斥变量。

7)、max_threads表示允许的最大线程数量、num_threads表示当前的线程数量、num_idle表示空闲的线程数量。之所以会有空闲进程,是因为当创建一个线程处理连接请求之后,它会保持一段时间空闲而不是直接销毁。如果这里再用新的连接到来或等待队列中有需要处理的连接,空闲进程会被分配去处理。

8)、thr_mutex、thr_cond、bind_mutex是用于互斥信号量和条件变量。

9)、queue[20]队列数组存储client的连接请求,每个元素都是client的socket。sq_head、sq_tail分别是队列头、尾用于操作队列queue。empty_cond、full_cond分别表示队列是否为空、满的条件变量。

10)、ssl_password_callback和log_callback都是函数指针,分别指向SSL密码处理函数、log处理函数。他们原型是:

/*

 * Register SSL password handler.

 * This is needed only if SSL certificate asks for a password. Instead of

 * prompting for a password on a console a specified function will be called.

 */

typedef int (*mg_spcb_t)(char *buf, int num, int w, void *key);

/*

 * User-defined callback function prototype for URI handling, error handling,

 * or logging server messages.

 */

typedef void (*mg_callback_t)(struct mg_connection *,

        const struct mg_request_info *info, void *user_data);

是上面讲了那么多感觉挺乱的,下面用张图片来形象表示一下:

                        图1、mg_context结构体的成员

2、mg_connection详解

故名思意,这个结构体用户保存client的连接信息。它的成员如下:

/*

 * Client connection.

 */

struct mg_connection {

    struct mg_request_info    request_info;

    struct mg_context *ctx;        /* Mongoose context we belong to*/

    SSL        *ssl;        /* SSL descriptor        */

    struct socket    client;        /* Connected client        */

    time_t        birth_time;    /* Time connection was accepted    */

    bool_t        free_post_data;    /* post_data was malloc-ed    */

    bool_t        embedded_auth;    /* Used for authorization    */

    uint_t    num_bytes_sent;    /* Total bytes sent to client    */

};

上面的字段意思都很明显这里就不一一阐述了。可以看出, 每个连接都保存了一个Mongoose上下文(mg_context * ctx),这个很重要,对连接请求进行处理时都会用到。这里也可以看出mg_context相当于一个实例句柄。

结构体mg_request_info用于保存每个请求的信息,例如,当我打开博客主页http://www.cnblogs.com/skynet/的时候,会发出一个请求信息,包括请求的方法是POST还是GET等、uri即http://www.cnblogs.com/skynet/、http版本、还有一些http头信息等等。关于结构体mg_request_info的详细信息参见下一小节。

mg_connection的图像表示如下:

图2、mg_connection结构体的成员

3、mg_request_info详解

这个结构体保存每次client发送请求,即是一个HTTP请求报文信息。而我们知道HTTP的请求报文信息的格式如下:

  图3、HTTP请求的格式

根据这个信息,可以更好地理解mg_request_info。mg_request_info结构定义如下:

/*

 * This structure contains full information about the HTTP request.

 * It is passed to the user-specified callback function as a parameter.

 */

struct mg_request_info {

    char    *request_method;    /* "GET", "POST", etc    */

    char    *uri;            /* Normalized URI    */

    char    *query_string;        /* \\0 - terminated    */

    char    *post_data;        /* POST data buffer    */

    char    *remote_user;        /* Authenticated user    */

    long    remote_ip;        /* Client's IP address    */

    int    remote_port;        /* Client's port    */

    int    post_data_len;        /* POST buffer length    */

    int    http_version_major;

    int    http_version_minor;

    int    status_code;        /* HTTP status code    */

    int    num_headers;        /* Number of headers    */

    struct mg_header {

        char    *name;        /* HTTP header name    */

        char    *value;        /* HTTP header value    */

    } http_headers[];        /* Maximum  headers    */

};

从字段都能够故名思意,这里就不再阐述了。

4、其他数据结构  

除了上面3个主要的数据结构,还有其它一些数据也默默地贡献着自己的一份力量。作为一个整体,少了它们Mongoose也只能沦为废物。下面我就列举几个:

/*

 * Structure used by mg_stat() function. Uses  bit file length.

 */

struct mgstat {

    bool_t        is_directory;    /* Directory marker        */

    uint_t    size;        /* File size            */

    time_t        mtime;        /* Modification time        */

};

struct mg_option {

    const char    *name;

    const char    *description;

    const char    *default_value;

    int        index;

    bool_t (*setter)(struct mg_context *, const char *);

};

/*

 * Structure used to describe listening socket, or socket which was

 * accept()-ed by the master thread and queued for future handling

 * by the worker thread.

 */

struct socket {

    SOCKET        sock;        /* Listening socket        */

    struct usa    lsa;        /* Local socket address        */

    struct usa    rsa;        /* Remote socket address    */

    bool_t        is_ssl;        /* Is socket SSL-ed        */

};

/*

 * Unified socket address. For IPv6 support, add IPv6 address structure

 * in the union u.

 */

struct usa {

    socklen_t len;

    union {

        struct sockaddr    sa;

        struct sockaddr_in sin;

    } u;

};

/*

 * Specifies a string (chunk of memory).

 * Used to traverse comma separated lists of options.

 */

struct vec {

    const char    *ptr;

    size_t        len;

};

/*

 * Dynamically loaded SSL functionality

 */

struct ssl_func {

    const char    *name;        /* SSL function name    */

    void        (*ptr)(void);    /* Function pointer    */

};

5、总结

至此,我们介绍了Mongoose中使用的一些数据结构,搞清楚这些数据结构对整个项目的理解非常重要。它们遍布在项目的每个角落(虽然项目比较小)。

作者:吴秦

出处:http://www.cnblogs.com/skynet/

本文基于署名 2.5 中国许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接).

文档

Mongoose源码剖析:数据结构篇

Mongoose源码剖析:数据结构篇作者:吴秦出处:http://www.cnblogs.com/skynet/本文基于署名2.5中国许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接).引言Mongoose中有几个数据结构扮演着重要的角色,它们分别是:•structmg_context:保存Mongoose的上下文,几乎每个函数都有mg_context参数•structmg_connection:保存HTPP连接信息•structmg_request_inf
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top