近期在研究crtmpserver,这里记录下学习过程,首先我们先分析下基本流程。
1、初始化流程
InitNetworking---初始化网络
Initialize
Logger::Init()---初始化日志
lowerCase(extension) == "lua"---载入.lua后缀配置文件
LoadLuaFile
Normalize
NormalizeLogAppenders
初始化日志配置
NormalizeApplications
初始化监听配置
gRs.pConfigFile->ConfigLogAppenders()依据配置初始化
IOHandlerManager::Initialize()
初始化IO,读写队列清零
gRs.pConfigFile->ConfigModules()
载入动态库appselector.dll
ProtocolFactoryManager::RegisterProtocolFactory(gRs.pProtocolFactory) 载入默认支持的协议集合
gRs.pConfigFile->ConfigAcceptors()
依据IP和port开启监听器
gRs.pConfigFile->ConfigInstances()
配置多实例,win下不支持
gRs.pConfigFile->ConfigApplications()
将监听器与实例绑定
installQuitSignal
设置程序退出机制
Run
IOHandlerManager::Pulse()
对socket资源进行轮询,查询是否有须要进行读写的socket操作
2、接收client的连接请求之connect
Pulse()
FD_ISSET(MAP_VAL(i)->GetInboundFd(), &_readFdsCopy)
MAP_VAL(i)->OnEvent(_currentEvent)
TCPAcceptor::Accept()
进入accept进行连接的创建
BaseProtocol *pProtocol = ProtocolFactoryManager::CreateProtocolChain
为连接创建相应配置的协议,比方tcp && rtmp,或者udp && rtcp==
TCPCarrier *pTCPCarrier = new TCPCarrier(fd)
为连接创建一个tcp交互对象,并将其和刚创建的协议对象绑定,创建时构造函数中就注冊了读请求
FD_ISSET(MAP_VAL(i)->GetInboundFd(), &_readFdsCopy)
MAP_VAL(i)->OnEvent(_currentEvent)
TCPCarrier::OnEvent(select_event &event)
进入读分支读取数据,根据相应的协议分析读取的数据根据结果填充_outputBuffer发送缓冲区,并设置发送信号TCPCarrier::SignalOutputData()--->ENABLE_WRITE_DATA,通知Pulse轮询socket状态须要发送数据,然后再次进入TCPCarrier::OnEvent(select_event &event)写分支进行真正的数据发送操作
RTMP消息类型为:RM_INVOKE_FUNCTION_CONNECT
3、接收client的公布流之Publish
这一段属于rtmp协议交互的部分
RM_INVOKE_FUNCTION_RELEASESTREAM
这里没有获得stream名称,发送名称请求
RM_INVOKE_FUNCTION_FCPUBLISH
这里获得stream名称
RM_INVOKE_FUNCTION_CREATESTREAM
ProcessInvokeCreateStream
pFrom->CreateNeutralStream(id) == NULL
RTMPStream *pStream = new RTMPStream
这里创建一个rtmpstream流控制对象 RTMPStream ---> BaseStream
RM_INVOKE_FUNCTION_PUBLISH
ProcessInvokePublish
GetApplication()->GetAllowDuplicateInboundNetworkStreams()这里推断是否存在同名情况
InNetRTMPStream *pInNetRTMPStream = pFrom->CreateINS(VH_CI(request) 创建network inbound stream
GetApplication()->GetStreamsManager()->GetWaitingSubscribers 查询是否有请求这路流的连接并绑定pBaseOutStream->Link(pInNetRTMPStream);
pInNetRTMPStream->SendOnStatusStreamPublished()
发送准备接收流请求
BaseOutFileStream *pOutFileStream = CreateOutFileStream(pFrom, meta, appending);另外,假设须要录像,这里创建文件流连接
4、接收client请求实时流
这一段属于rtmp协议交互的部分
RM_INVOKE_FUNCTION_PLAY
ProcessInvokePlay
pFrom->CloseStream(VH_SI(request), true)
关闭该连接之前请求的流
TryLinkToLiveStream(pFrom, VH_SI(request), streamName, linked)
将该连接绑定
FOR_MAP(inboundStreams, uint32_t, BaseStream *, i)
通过streamName查询找到流输入
BaseOutNetRTMPStream * pBaseOutNetRTMPStream = pFrom->CreateONS(streamId, 先创建流输出
pBaseInNetStream->Link(pBaseOutNetRTMPStream)
然后将流输出绑定至流输入