过程拿rtmp系列模块举例说明,其他系列模块类似,大同小异,比如http,由此推导即可。
-
解析端口
ngx_init_cycle函数发起cycle初始化,程序启动加载配置,解析到server块配置项(cmd的类型为block)的时候,其下会有直属的listen配置项,这个配置项由系列模块的core模块(ngx_rtmp_core_module)来解析。在解析rtmp块配置项的时候产生了rtmp配置块下的ctx,其main层ctx(ngx_rtmp_core_main_conf_t)里有一个listen数组,listen配置项处理完了会保存在这里。而这个时候也会把相应的server配置块下创建的ctx赋值给listen的ctx属性,以便session建立的时候直接找到其对应的main、server级别的配置ctx。 -
建立监听、处理连接
rtmp块配置项解析的最后,调用ngx_rtmp_optimize_servers函数处理每一个监听,里面会调用ngx框架的ngx_create_listeing函数去建立监听。其中会把监听的handler属性赋值为rtmp模块的连接初始化函数ngx_rtmp_init_connection。之后ngx_init_cycle函数会调用ngx_open_listening_sockets开启端口监听。之后框架会进入init process的阶段,事件系列模块的core module在这个阶段的处理函数为ngx_event_process_init,里面会给每一个监听添加一个connection,这个connection的read事件的handler会根据socket类型(这里只说tcp)赋值为ngx_event_accept,之后调用ngx_add_event宏把这个read事件加入到epoll事件循环之中。回调函数ngx_event_accept里面会赋值connection的recv和send函数指针,用于处理socket读写,之后调用ngx_listening_t的handler,即前面说到的解析配置时初始化的监听handler。启动后,一旦事件模块的epoll收到了请求连接的事件(tcp syn)并成功accept(accept4)之后,就会回调这个handler,就进入了rtmp系列模块的处理。
至此,建立监听和处理连接过程就介绍完了。 -
连接后的处理
一旦连接建立,则事件模块会回调相应的处理模块的函数,对于rtmp系列模块来说就是ngx_rtmp_init_connection函数。这个函数里会创建和初始化一个session,之后调用ngx_rtmp_handshake开启握手。ngx_rtmp_handshake里会将此session的connection的读写事件的回调设置为握手逻辑的回调,之后开始处理握手。握手成功之后,会调用ngx_rtmp_cycle进入rtmp逻辑主循环,里面会把连接的读写事件赋值成相应的回调。之后会直接调用ngx_rtmp_recv来读取数据处理,一旦遇到EAGAIN,就把这个事件加入到epoll(无需担心重复添加,因为一旦ngx_handle_(read、write)_event成功,事件的active标志位会置为1,而为1之后就不会再add到epoll了)。
至此,连接后的处理就介绍完毕了。 -
总结
可以看出,整个建立连接以及连接之后的处理都是通过对事件的回调handler属性的不断变换赋值实现的逻辑控制。