ngx_rtmp_handler 是 Nginx RTMP 模块中的核心处理部分,主要负责处理 RTMP 流会话中的数据接收、发送、ping 操作以及分块大小的设置等。
1. 全局变量
-
ngx_rtmp_naccepted
: 记录接受的 RTMP 连接数。 -
ngx_rtmp_bw_out
和ngx_rtmp_bw_in
: 分别表示输出带宽和输入带宽,用于监控 RTMP 会话的数据流量。
2. 主要处理函数
2.1 ngx_rtmp_cycle
函数
这个函数是 RTMP 会话的核心调度函数。它设置了 RTMP 会话的数据读取和发送回调函数,并初始化了 Ping 事件(用于保持与客户端的连接)。
-
ngx_rtmp_recv
: 用于处理 RTMP 数据接收事件。 -
ngx_rtmp_send
: 用于处理 RTMP 数据发送事件。 -
ngx_rtmp_ping
: 用于处理 RTMP 心跳请求。
该函数还会调用 ngx_rtmp_reset_ping
来重置 Ping 事件,确保 RTMP 会话的活跃性。
2.2 ngx_rtmp_alloc_in_buf
函数
用于为 RTMP 会话分配输入缓冲区。通过调用 ngx_alloc_chain_link
和 ngx_calloc_buf
函数,分配内存来存储接收到的数据。数据存储在 ngx_chain_t
链表结构中,方便多次处理。
2.3 ngx_rtmp_reset_ping
函数
这个函数用于重置心跳机制。如果配置了 Ping 超时(cscf->ping
),会启用心跳定时器,定期向客户端发送 Ping 请求,以保持连接的活跃状态。
2.4 ngx_rtmp_ping
函数
处理心跳事件。如果在指定时间内没有收到 Ping 响应,则会认为客户端超时,调用 ngx_rtmp_finalize_session
来关闭该会话。
-
如果 Ping 请求超时或连接繁忙,会记录错误日志并终止会话。
-
如果 Ping 请求成功发送,会设置下一次 Ping 事件的定时器。
2.5 ngx_rtmp_recv
函数
这是处理 RTMP 数据接收的主要函数。它执行以下任务:
-
从客户端接收数据并将数据存储在输入缓冲区中。
-
处理分块数据:如果数据分块未完成,会继续接收数据并重组。
-
解析 RTMP 包头信息(如时间戳、数据长度等)。
-
处理不同类型的 RTMP 消息,并根据数据流的标识符 (
csid
) 将数据分配到正确的流中。 -
如果接收到的消息类型有效,会调用
ngx_rtmp_receive_message
来进一步处理消息。
2.6 ngx_rtmp_send
函数
用于发送 RTMP 数据。该函数会检查是否有待发送的数据,按照优先级将数据发送到客户端。如果发送的数据需要等待,则会设置一个定时器,并尝试在下一个时刻继续发送。
-
使用
ngx_rtmp_send
进行数据发送,确保 RTMP 数据包能够及时地推送到客户端。 -
如果网络状况不好,可能会出现超时、写事件阻塞等情况,此时会处理相应的错误或重试。
2.7 ngx_rtmp_prepare_message
函数
此函数负责为 RTMP 消息准备消息头,计算消息的时间戳、大小、类型等信息。它为每个 RTMP 消息生成一个特定格式的头部。
-
根据消息的格式(
fmt
)选择不同的头部结构。 -
支持 RTMP 消息的扩展时间戳(
ext_timestamp
),这是为了解决大时间戳的问题(RTMP 协议标准只支持 24 位时间戳,而实际中可能会有更大的时间戳)。 -
通过
ngx_rtmp_message_type
函数,生成消息类型的描述(如音频、视频、命令消息等)。
3. RTMP 分块与流控制
RTMP 协议支持将数据分为多个分块进行传输。在 Nginx RTMP 模块中,分块的处理和流控制非常重要,特别是在处理大的数据流(如视频流)时,分块可以提高数据传输的效率。
-
分块大小设置 (
ngx_rtmp_set_chunk_size
):-
设置每个 RTMP 分块的大小。如果接收到的块大小超过了指定的最大值,返回错误并终止会话。
-
会为每个连接创建一个新的内存池,并调整 RTMP 会话的输入缓冲区大小。
-
-
流控制:
-
使用
ngx_rtmp_send_message
来处理消息队列。如果消息队列已满,可能会丢弃某些数据包,确保队列不会超载。 -
支持根据不同的优先级进行数据包的推送,以确保高优先级数据的及时传输。
-
4. 总结
这段代码主要实现了 RTMP 会话的生命周期管理,特别是数据的接收、发送、流控制和心跳机制。每个 RTMP 会话都通过一系列的回调函数和事件处理机制,确保数据能够正确流动并处理超时等异常情况。
-
RTMP 分块与流控制:理解 RTMP 协议如何通过分块(chunking)来处理大流数据,模块如何管理每个流的输入和输出缓冲区。
-
心跳机制:RTMP 会话如何通过心跳(ping/pong)机制保持与客户端的连接活跃。
-
消息头和流类型:如何解析和生成 RTMP 消息头,并通过流标识符(
csid
)将消息发送到正确的流。 -
错误处理和会话终止:如何处理超时、网络错误和流量限制等问题。
这个模块是 RTMP 协议实现的核心,涉及的数据流控制、错误管理和性能优化都非常关键,理解这些内容有助于深入掌握 Nginx RTMP 模块的工作原理。