17.live555mediaserver-保活机制

live555工程代码路径
live555工程在我的gitee下(doc下有思维导图、drawio图):
live555
https://gitee.com/lure_ai/live555/tree/master

章节目录链接
0.前言——章节目录链接与为何要写这个?
https://blog.csdn.net/yhb1206/article/details/127259190?spm=1001.2014.3001.5502

学习demo
live555mediaserver.cpp

学习线索和姿势
1.学习的线索和姿势

网络编程
流媒体的地基是网络编程(socket编程)。
[网络编程学习]-0.学习路线

绘图规则
本文的对象图和思维导图遵守的规则详见:
2.绘图规则

非阻塞服务端网络编程流程
socket创建、bind、listen、select、accept、select、recv/send-close。

rtsp协商流程
options、describe、setup、play、pause、teardown、get parameter、set parameter

rtp打包流程
打开媒体文件、读取一帧媒体数据、rtp打包、rtp发送

本节内容和目标
(1)live555mediaserver的保活机制
(2)rtcp协议学习
(3)wireshark抓包
(4)对象图

正式开始

回顾14.live555mediaserver-setup请求与响应 ,从第一个setup开始,创建了新对象 RTSPServer::RTSPClientSession ,而它就引入了server端的保活机制——其父类实现的 noteLiveness 方法。设置65s的alarm的定时器加入定时器列表,如果超过65s则server端断开rtsp链接。接下来第2次setup或者play等都会调用noteLiveness 来刷新这个65s的时间。注意这个是客户端下方setup或play,server来被动刷新这个时间的。

注册回调

那么play之后,server端不断发送rtp包,它是如何刷新的呢?那就要找下 noteLiveness 注册给谁了,如下

在这里插入图片描述
在这里插入图片描述

可以看到在play时把 GenericMediaServer::ClientSession::noteClientLiveness 这个静态方法注册到回调里去了,它其实质就是调用的 noteLiveness 。
看下它注册到哪里去了,追踪下:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
可以看到它最终放到rtcp对象里的fSpecificRRHandlerTable表格里了,可以猜测是rtcp接管了这个保活。这个注册回调完毕。

调用回调

那么在哪调用呢?追踪下:
在这里插入图片描述
哦,原来是noteArrivingRR直接调用它的,那么谁调用noteArrivingRR呢?继续:
在这里插入图片描述
RTCPInstance::processIncomingReport调用的,大概意思也就是说在收到客户端的rtcp的接收⽅报告RR的时候才会调用noteArrivingRR方法,然后自然刷新保活。

那么再追踪谁调用的RTCPInstance::processIncomingReport:
在这里插入图片描述
是RTCPInstance::incomingReportHandler1()调用的 RTCPInstance::processIncomingReport。

那么又是谁调用的 RTCPInstance::incomingReportHandler1()?
是由静态方法RTCPInstance::incomingReportHandler调用的。

那么静态方法RTCPInstance::incomingReportHandler又是谁调用的呢?回头看下RTCP对象创建的时机
在这里插入图片描述
StreamState::startPlaying 创建RTCPInstance对象关联到成员fRTCPInstance。那么创建这个对象的构造函数干了啥呢?
在这里插入图片描述在这里插入图片描述
RTCPInstance对象的构造函数里会将静态方法RTCPInstance::incomingReportHandler通过对象RTPInterface的方法startNetworkReading注册到socket任务里的,如下
在这里插入图片描述
这个socket任务如何注册的可以参见4.live555mediaserver-第一次select,不再赘诉。

其对象图如下
在这里插入图片描述

另外,在15.live555mediaserver-rtp打包与发送知道音视频的rtp发送是根据帧率计算定时间隔,创建定时器任务加入定时器列表里。现在呢,又注册了一个socket任务用于发送和接受客户端的rtcp包。

这就是涉及到rtcp了,参见好文章RTCP协议讲解

总之呢,就是server端发送rtcp信息到客户端,客户端回包,接受到客户端的rtcp回包类型是RR的时候才会刷新这个保活,保持这个链接不断。wireshark抓包看下。

在这里插入图片描述
抓包看,RR包有时间隔不到1s又时间隔4s,具体间隔不太懂,rtcp协议不懂得看下。

加日志看下
搜索关键字delete alarmHandler|PLAY rtsp|fLivenessCheckTask|SETUP rtsp
发现下
在这里插入图片描述
setup开始加入65s的定时任务,setup和play会刷新,那么rtp发送后确实是由rtcp来接管了,每次收到RR后才会刷新这个65s的定时任务。

补充说明

以上是udp是这样的。但是在rtp over tcp模式下,这个保活的回调是注册给如下的:
在这里插入图片描述
可以看到tcp下创建了socket链表成员,把tcp的socket、静态方法 SocketDescriptor::tcpReadHandler 和SocketDescriptor的this指针作为属性绑定一起的。同时把静态方法 RTCPInstance::incomingReportHandler 注册给对象RTPInterface的成员函数指针变量fReadHandlerProc。

然后当收到rtcp数据时,回调静态方法 SocketDescriptor::tcpReadHandler,然后如下调用链:
在这里插入图片描述

最终调用静态方法 RTCPInstance::incomingReportHandler ,然后如文前所述,就能调到保活的回调GenericMediaServer::ClientSession::noteClientLiveness。

小结

由果寻因、由上到下、倒推的探索了server端的保活机制,最后发现是由rtcp接管了。接受到RTCP的RR时才会刷新,这样保活的。这个保活机制和我想象的不一样。
另外顺序看的话,应该是这样的:
在这里插入图片描述
先是创建rtcp对象,构造函数里创建了个soket任务加入到socket链表里了,接着把GenericMediaServer::ClientSession::noteClientLiveness 这个静态方法注册到这个rtcp对象里了。
当客户端端回rtcp包时,socket任务被激活,执行静态方法RTCPInstance::incomingReportHandler,然后一系列处理——需要特别指出的是,如果回包是RR类型的话,就会调用回调GenericMediaServer::ClientSession::noteClientLiveness 这个静态方法来刷先保活时间。
这就是顺序流程。
这个是rtp over udp。
tcp走的则是另外一个流程,上面说了,不再赘述。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值