学习《apache源代码全景分析》之网络连接部分摘录

1.MPM框架负责多进程或多线程的并发处理,它侦听指定的套接字,一旦客户端请求到来,它将立即接受该请求,并创建相应的连接。而一旦连接建立完毕,核心将从该连接上读取请求的数据。

  

整个HTTP连接处理的过程可以分为下面几大部分:

   (1) 接收连接

   (2) 创建连接

   (3) 连接预处理

   (4) 请求处理

   (5) 清除连接和关闭连接

2.等待连接的过程就是调用套接字函数listen的过程。Apache中使用封装后的APR函数ap_setup_listeners进行侦听。对于MPM来说,该函数在挂钩open_logs被调用的时候触发。

3.Apache核心将创建一个conn_rec结构,连接的创建通过create_connection挂钩完成。

struct conn_rec
{
    apr_pool_t *pool;
    server_rec *base_server;
    void *vhost_lookup_data;

    apr_sockaddr_t *local_addr;
    apr_sockaddr_t *remote_addr;
    char *remote_ip;
    char *remote_host;
    char *remote_logname;
    char *local_ip;
    char *local_host;

    ap_conn_keepalive_e keepalive;
    signed int double_reverse:2;
    int keepalives;

    unsigned aborted:1;

    long id;
    struct ap_conf_vector_t *conn_config;
    apr_table_t *notes;
    struct ap_filter_t *input_filters;
    struct ap_filter_t *output_filters;
    void *sbh;
    struct apr_bucket_alloc_t *bucket_alloc;
    conn_state_t *cs;

    int data_in_input_filters;
    
    int clogging_input_filters;
};

4.套接字绑定和侦听流程:

扫描二维码关注公众号,回复: 3757452 查看本文章

   

   open_listeners内部的主要工作包括三部分:

     (1) 对于每一个套接字,调用make_sock函数,将其与给定的IP地址/端口绑定在一起,同时在指定的端口上进行侦听。

     (2) 如果本次是重新启动,那么启动前的侦听套接字都保存在old_listeners中,这些侦听套接字都不再需要了,此时必须将它们逐一关闭;

     (3) 注册侦听套接字内存池清理函数。

 

     conn_rec中的notes字段的作用:它通常类似于一个中介传输者,在不同的模块和不同的函数之间传递一个信息。通常情况下某个函数将须要传递其余函数的信息设置在notes中,其余的函数则相应从中获取,类似于一个传送带,如下图:

     

     一旦建成conn_rec结构,MPM模块将会调用ap_process_connection()对该连接进行进一步处理。ap_process_connection()是整个Apache的核心部分,至此,Apache将脱离MPM模块的控制,进入请求-响应循环。

    

  (1) 使用ap_update_vhost_given_ip()函数确定该连接IP地址所对应的所有虚拟主机;

  (2) 调用pre_connection挂钩。

  (3) 调用process_connection挂钩处理该连接。

5.pre_connection阶段的一项重要任务就是在过滤器堆栈中插入新的连接过滤器。

    目前Apache中实现该挂钩的模块包括: core、ssl模块、nw_ssl、logio模块、dumpio模块

    总而言之,在处理连接之前需要做的任何与连接相关的准备工作都可以放到pre_connection中去处理。

6.HTTP连接处理的主要内容包括两方面:读取连接上的请求数据及处理这些请求数据。Apache中通过ap_read_request函数完成一次请求读取,而请求的处理则由函数ap_process_request完成。

7.一个HTTP请求连接通常会对应多个request_rec结构

    

8.请求读取实现

   

   请求读取流程:

   

9.HTTP/1.1 协议规定(RFC2616 14.23节),浏览器必须发送host请求头,因此,当发现协议为1.1.版本时,同时却没有告知完整的URL或没有在请求行中请求host域,这种情况是不允许的,此时将直接发送错误响应,返回错误码为400.

10.如果服务器收到的头信息存在Expect域,同时值为100-continue的请求,这是指客户端询问是否可以在后续的请求中发送附件。在这种情况下,服务器用100(SC_CONTINUE)允许客户端继续或用417(Expectation Failed)告诉客户端不同意接受附件。这个状态码是HTTP 1.1中新加入的。如果存在非空的Expect头域,同时值为"100-continue",则将请求的expecting_100设置为1,这样返回给客户端,允许继续发送附件。如果请求头域的值无法识别,那么进行出错处理,发送响应,记录日志。

11.请求头的读取使用ap_get_mime_headers_core实现。

12.实际报文的逐行读取是通过函数ap_rgetline完成的,该函数的内部调用了ap_rgetline_core函数。ap_rgetline_core函数完成实际的IO读取工作。

猜你喜欢

转载自blog.csdn.net/zhangge3663/article/details/83344029