《SRS原理》上架了,深度剖析 SRS 源代码,访问地址:srs.xianwaizhiyin.net
本文采用的 SRS 版本是 4.0-b8 , 下载地址:github
《SRS4.0源码分析-RTMP入口》 讲解了 建立 RTMP 的入口是在 SrsServer::fd_to_resource()
函数,现在就来验证一下是不是真的在那里,断点调试很重要,有时候看代码会看错,现在就在 fd_to_resource() 函数打个断点,如下图:
果然,有 RTMP 请求来的时候,SRS
代码就会跑进去 new SrsRtmpConn()
,所以之前的分析没有错误。
本文 就来分析 SrsRtmpConn
类的逻辑。SrsRtmpConn
类的构造函数比较简单,如下:
注意上面第二个参数srs_netfd_t c
,这个是 ST
库的 fd
,对原始的 tcp fd 封装了一下,推荐阅读《ST源码分析-server》
SrsRtmpConn::SrsRtmpConn()
只有一个重点,就是创建了一个协程来处理这个 客户端的 TCP 链接。其他的代码我也简单过一下,如下:
_srs_context->set_id(_srs_context->generate_id());
_srs_context
是一个全局变量,主要是用来生成唯一ID,做日志跟踪的。这个变量跟上下文切换没有太大关系。请看后续文章《SRS4.0源码分析-_srs_context》
PS: SRS 里面 以 _ 开始的变量全都是全局变量。
skt = new SrsTcpConnection(c);
上面是创建一个 Tcp链接管理器,方便后面对这个 fd
进行读写。
clk = new SrsWallClock();
类 SrsWallClock
应该是一个时钟,请看后续文章《SRS4.0源码分析-SrsWallClock》
kbps = new SrsKbps(clk);
类 SrsKbps
是用来统计 IO 流量的,请看后续文章《SRS4.0源码分析-流量统计》
然后就是重点代码 new SrsSTCoroutine()
,从之前的文章可以知道多次出现 new SrsSTCoroutine()
,所以这个函数应该就是 SRS 创建协程的封装函数。这里讲解一下这个类的用法。请看下图:
第一个参数 n
是 rtmp
,这个是个字符串,标记是什么类型的协程。
第二个参数 h
就是重点,全部都是用 this
,这是一种多态用法。这个 this
类要实现一个 cycle()
函数,然后协程运行的时候,就会跑到 cycle()
函数不断循环处理,在此刻 this
是 SrsRtmpConn
。
第三个参数 cid
是协程ID。可以理解为生成一个唯一标示。
所以,如果你要二次开发,你创建自己的协程的时候,需要新建一个类,实现一个 cycle()
函数,然后 丢进去 new SrsSTCoroutine()
函数就行。
这里虽然创建了协程,但是当前逻辑还没执行到 ST 库的阻塞函数,所以新创建的协程还未开始运行,代码还是会继续往下走。注意一点,用ST的协程,只有遇到阻塞函数才会开始切换上下文。
rtmp = new SrsRtmpServer(skt);
这个 SrsRtmpServer
类,不是监听端口,而是处理 RTMP握手逻辑的,可以理解为RTMP链接的管理器。这里提及一下,RTMP协议的实现大部分都在 srs_rtmp_stack.cpp
文件里面。
refer = new SrsRefer();
检测 refer,跟 http 的 refer 差不多,来源
bandwidth = new SrsBandwidth();
带宽检测,CDN,由于SRS刚开始的业务场景是 CDN,所以需要计算流量做带宽限制之类的。
security = new SrsSecurity();
这个是安全检测,允许哪些客户端可以进行推流拉流,具体请看《SRS4.0源码分析-鉴权原理》
wakable = NULL;
这个 wakable
变量比较有趣,注意一下。暂时跳过
mw_sleep = SRS_PERF_MW_SLEEP;
这个是协程休眠阻塞,等收到了8个音视频包后,才会转发给播放器,达到合并写功能,能优化IO效率,具体请看《SRS为何能做到同类的三倍》,搜索 合并写入 即可。
_srs_config->subscribe(this);
上面这句代码应该是为了 reload 配置文件的时候,能有所响应,应该是注册一个 reload 的处理事件。
执行完上面的代码之后,SrsRtmpConn::SrsRtmpConn()
这个函数就退出了,只需要记得,里面创建了一个协程 函数 SrsRtmpConn::cycle()
。
到这里,SrsRtmpConn::SrsRtmpConn()
构造函数已经分析完毕。
具体在 TCP 的基础上建立 RTMP 链接的逻辑就会在 协程 SrsRtmpConn::cycle()
里面处理。下一篇文章就来 分析 SrsRtmpConn::cycle()
的逻辑。
由于笔者的水平有限, 加之编写的同时还要参与开发工作,文中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果读者有任何宝贵意见,可以加我微信 Loken1。QQ:2338195090。