您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
免费发信息

hello模块的编写

2024/4/17 1:15:23发布6次查看
为了学习高性能并发服务器,打算研究一下nginx的实现。按照惯例,最开始都要写一个hello world的程序,所以接下来就是介绍如何在nginx的框架下编写一个简单的http模块来打印”hello world“。
定义hello配置项的处理
首先,我们需要定义一个commands数组用来定义模块的配置文件参数。每一个数组元素都是ngx_command_t类型,数组的结尾用ngx_null_command结尾。
nginx在解析配置文件中的一个配置项时首先会遍历所有的模块,对于每个模块而言,即通过遍历commands数组进行。每一个ngx_command_t结构体定义了自己感兴趣的一个配置项。该结构定义如下:
struct ngx_command_s { /* 配置项名称 */ ngx_str_t name; /* 指定配置项可以出现的位置 */ ngx_uint_t type; /* 出现了name中指定的配置项后,将会调用set方法处理配置项的参数 */char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); ngx_uint_t conf; /* 在配置文件中的偏移量 */ ngx_uint_t offset; /* 配置项读取后的处理过程,必须是ngx_conf_post_t结构的指针 */void *post;};#define ngx_null_command { ngx_null_string, 0, null, 0, 0, null }
了解了commands数组后,我们定义hello配置项的处理:
static ngx_command_t ngx_http_hello_commands[] = { { ngx_string(hello), ngx_http_loc_conf|ngx_conf_noargs, ngx_http_hello, ngx_http_loc_conf_offset, 0, null }, ngx_null_command};
其中,ngx_http_hello是ngx_command_t结构体中的set成员,当在某个配置块中出现hello配置项时,nginx会调用ngx_http_hello方法。下面是ngx_http_hello的实现:
staticchar *ngx_http_hello(ngx_conf_t *cf, ngx_command_t *cmd, void *conf){ ngx_http_core_loc_conf_t *clcf; /* 首先找到hello配置项所属的配置块 */ clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); /* http框架在处理用户请求进行到ngx_http_content_phase阶段时 * 如果请求的主机域名、uri与hello配置项所在的配置块相匹配 * 则调用ngx_http_hello_handler方法处理这个请求 */ clcf->handler = ngx_http_hello_handler; return ngx_conf_ok;}
定义hello模块
定义一个http模块的方式很简单,只要像下面这样定义一个ngx_moodule_t的结构体:
ngx_module_t ngx_http_hello_module = { ngx_module_v1, &ngx_http_hello_module_ctx, /* module context */ ngx_http_hello_commands, /* module directives */ ngx_http_module, /* module type */ null, /* init master */ null, /* init module */ null, /* init process */ null, /* init thread */ null, /* exit thread */ null, /* exit process */ null, /* exit master */ ngx_module_v1_padding};
则hello模块在编译时将会被加入到ngx_modules全局数组中。
其中ngx_http_hello_commands就是前一节我们定义的hello配置项的处理。
因为我们定义的是http模块,所以type要设置成ngx_http_module。
还有一个重要的成员void* ctx,对于http模块来说,ctx指针必须指向ngx_http_module_t接口。
http框架在读取、重载配置文件时定义了由ngx_http_module_t接口描述的8个阶段,http框架在启动的时候会在每个阶段中调用ngx_http_module_t中相应的方法。如果不需要做什么工作,则可以定义为null。因为hello模块不需要做什么工作,所以定义如下:
static ngx_http_module_t ngx_http_hello_module_ctx = { null, /* preconfiguration */ null, /* postconfiguration */ null, /* create main configuration */ null, /* init main configuration */ null, /* create server configuration */ null, /* merge server configuration */ null, /* create location configuration */ null /* merge location configuration */};
处理用户请求
最后就是处理用户请求了,这里需要一点http的知识,可以参考http协议入门。我们是通过实现ngx_http_hello_handler方法来处理用户的请求了,该方法定义如下:
static ngx_int_tngx_http_hello_handler(ngx_http_request_t *r)
其中ngx_http_request_t结构体中包含了请求的所有信息(如方法,uri,协议版本号和头部等),除此之外,还包含了其他很多成员,例如内存池,响应报头等等。
因为我们只处理get方法和head方法,所以需要做如下判断:
if (!(r->method & (ngx_http_get | ngx_http_head))) { return ngx_http_not_allowed; }
接下来因为我们不需要请求中的包体,所以需要丢弃掉包体,方法如下:
ngx_int_t rc = ngx_http_discard_request_body(r);if (rc != ngx_ok) { return rc;}
然后是设置返回的响应包,返回的包体只包含一个”hello world”字符串:
ngx_str_type = ngx_string(text/plain);ngx_str_response = ngx_string(hello world);r->headers_out.status = ngx_http_ok;r->headers_out.content_length_n = response.len;r->headers_out.content_type = type;
最后就是发送响应包的包头和包体了:
rc = ngx_http_send_header(r); if (rc == ngx_err || rc > ngx_ok || r->header_only) { return rc; } ngx_buf_t *b; b = ngx_create_temp_buf(r->pool, response.len); if (b == null) { return ngx_http_internal_server_error; } ngx_memcpy(b->pos, response.data, response.len); b->last = b->pos + response.len; b->last_buf = 1; ngx_chain_t out; out.buf = b; out.next = null; /* send the buffer chain of your response */return ngx_http_output_filter(r, &out);
完整代码可以在这里查看:hello_module
编译和运行
在代码同目录下新建一个config文件,添加这样几行:
ngx_addon_name=ngx_http_hello_modulehttp_modules=$http_modules ngx_http_hello_modulengx_addon_srcs=$ngx_addon_srcs$ngx_addon_dir/ngx_http_hello_module.c
然后进入nginx的源码根目录,运行configure,记得带上–add-module参数,在参数后面接上我们自己编写的http模块代码所在的路径:
./configure --prefix=/usr/local/nginx --add-module=/code/nginx-1.8.0/src/http/hello_module
configure运行完成后,用make命令来编译,编译成功后输入make install完成安装。
修改/usr/local/nginx/conf/nginx.conf,添加:
http{ ... server { ... location /hello { hello; } ... } ...}
运行nginx,然后在浏览器输入ip/hello就可以看到显示的”hello world字符串了“。
参考
《深入理解nginx》
以上就介绍了 hello模块的编写,包括了方面的内容,希望对php教程有兴趣的朋友有所帮助。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录