游戏后台开发
分类: 服务器与存储
2013-12-01 00:59:57
01 | struct ngx_connection_s { |
02 | void *data; // 将要关联的模型,listening, request, ... 或其它 |
03 | ngx_event_t *read; // 读事件 |
04 | ngx_event_t *write; // 写事件 |
05 |
06 | ngx_socket_t fd; // 句柄 |
07 |
08 | ngx_listening_t *listening; // 对应的监听 |
09 | }; |
10 |
11 | struct ngx_event_s { |
12 | void *data; // 将要关联的模型,connection, ... 或其它 |
13 |
14 | unsigned write:1; // 是否可写 |
15 |
16 | unsigned accept:1; // 是否是accept产生的事件 |
17 |
18 | unsigned instance:1; // 避免惊群的一个设计 |
19 |
20 | unsigned active:1; // 是否有效,当加入epoll_ctl时就置为1 |
21 |
22 | unsigned ready:1; // epoll_wait捕获到时就置为1 |
23 |
24 |
25 | unsigned timedout:1; // 是否超时 |
26 | unsigned timer_set:1; // 是否置为定时器,即加入超时定时器红黑树时就置为1 |
27 |
28 |
29 | ngx_event_handler_pt handler; // 事件处理函数,核心 |
30 |
31 |
32 | ngx_rbtree_node_t timer; // 加入红黑树时需要的辅助节点 |
33 | }; |
01 | struct ngx_cycle_s { |
02 | ... |
03 | ngx_array_t listening; // 是个数组,结构体为ngx_listening_s |
04 | ... |
05 | } |
06 |
07 | struct ngx_listening_s { |
08 | ngx_socket_t fd; // 句柄描述符 |
09 |
10 | struct sockaddr *sockaddr; |
11 | socklen_t socklen; |
12 | ... |
13 | }; |
01 | struct ngx_http_request_s { |
02 | uint32_t signature; /* "HTTP" */ |
03 |
04 | ngx_connection_t *connection; // 对应的连接 |
05 |
06 | /* 这个结构体是非常庞大的,但不复杂,比如它处理了并重新保存了配置文件的上下文 */ |
07 | void **ctx; |
08 | void **main_conf; |
09 | void **srv_conf; |
10 | void **loc_conf; |
11 |
12 | /* 比如请求有关的信息的会保存到它的成员里 */ |
13 | u_char *uri_start; |
14 | u_char *uri_end; |
15 | u_char *uri_ext; |
16 | u_char *args_start; |
17 | u_char *request_start; |
18 | u_char *request_end; |
19 | u_char *method_end; |
20 | u_char *schema_start; |
21 | u_char *schema_end; |
22 | u_char *host_start; |
23 | u_char *host_end; |
24 | u_char *port_start; |
25 | u_char *port_end; |
26 |
27 | unsigned http_minor:16; |
28 | unsigned http_major:16; |
29 | }; |
01 | ngx_event_expire_timers(void) |
02 | { |
03 | ... |
04 |
05 | for ( ;; ) { |
06 |
07 | node = ngx_rbtree_min(root, sentinel); |
08 |
09 | /* node->key <= ngx_current_time,很简单巧妙的设计,怎么视为超时 */ |
10 |
11 | if ((ngx_msec_int_t) (node->key - ngx_current_msec) <= 0) { |
12 | ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer)); |
13 |
14 | ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer); |
15 |
16 | ev->timer_set = 0; // 重置timer_set |
17 | ev->timedout = 1; // 标记为超时 |
18 |
19 | ev->handler(ev); // 马上处理,注意这里没有处理成如果超时就关闭连接,这是由handler自行处理的 |
20 | // 后面会再解释这个设计 |
21 |
22 | continue; |
23 | } |
24 |
25 | break; // 如果没有超时的事件,结束退出 |
26 | } |
27 | } |
01 | for ( ;; ) { |
02 | timer = ngx_event_find_timer(); |
03 |
04 | events = epoll_wait(ep, event_list, (int) nevents, timer); |
05 |
06 | ;更新时间 |
07 |
08 | ;超时处理 |
09 |
10 | ;正常事件处理 |
11 | } |
01 | ngx_http_init_request(ngx_event_t *rev) |
02 | { |
03 | ... |
04 |
05 | if (rev->timedout) { |
06 | ngx_http_close_connection(c); |
07 | return; |
08 | } |
09 |
10 | ... |
11 | } |
12 |
13 |
14 | ngx_http_process_request_line(ngx_event_t *rev) |
15 | { |
16 | ... |
17 |
18 | if (rev->timedout) { |
19 | c->timedout = 1; |
20 | ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); |
21 | return; |
22 | } |
23 |
24 | ... |
25 | } |
01 | ngx_url_t u; |
02 | ngx_peer_connection_t peer; |
03 |
04 | ngx_memzero(&u, sizeof(ngx_url_t)); |
05 | ngx_memzero(&peer, sizeof(ngx_peer_connection_t)); |
06 |
07 | ngx_str_set(&u.url, "127.0.0.1:8080"); |
08 |
09 | ngx_parse_url(pool, &u); |
10 |
11 | peer.sockaddr = u.addrs->sockaddr; |
12 | peer.socklen = u.addrs->socklen; |
13 | peer.name = u.addrs->name; |
14 | peer.get = ngx_event_get_peer; |
15 |
16 | ngx_event_connect_peer(&peer); |
17 |
18 | peer.connection->read->handler = ngx_mail_auth_http_read_handler; |
19 | peer.connection->write->handler = ngx_mail_auth_http_write_handler; |
20 |
21 | ngx_add_timer(peer.connection->read, ahcf->timeout); |
22 | ngx_add_timer(peer.connection->write, ahcf->timeout); |