srs在启动初始化,配置等完成后,开始执行socket监听:
int run_master()
{
int ret = ERROR_SUCCESS;
...
if ((ret = _srs_server->listen()) != ERROR_SUCCESS) {
return ret;
}
...
return 0;
}
int SrsServer::listen()
{
int ret = ERROR_SUCCESS;
if ((ret = listen_rtmp()) != ERROR_SUCCESS) {
return ret;
}
if ((ret = listen_http_api()) != ERROR_SUCCESS) {
return ret;
}
if ((ret = listen_http_stream()) != ERROR_SUCCESS) {
return ret;
}
if ((ret = listen_stream_caster()) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
我们只关注listen_rtmp即可:
int SrsServer::listen_rtmp()
{
int ret = ERROR_SUCCESS;
// stream service port.
std::vector<std::string> ip_ports = _srs_config->get_listens();
srs_assert((int)ip_ports.size() > 0);
close_listeners(SrsListenerRtmpStream);
for (int i = 0; i < (int)ip_ports.size(); i++) {
SrsListener* listener = new SrsStreamListener(this, SrsListenerRtmpStream);
listeners.push_back(listener);
std::string ip;
int port;
srs_parse_endpoint(ip_ports[i], ip, port);
if ((ret = listener->listen(ip, port)) != ERROR_SUCCESS) {
srs_error("RTMP stream listen at %s:%d failed. ret=%d", ip.c_str(), port, ret);
return ret;
}
}
return ret;
}
这里根据配置,启动了多个监听器监听多个端口,但我们一般上就用一个1935端口。
继续看:
int SrsStreamListener::listen(string i, int p)
{
int ret = ERROR_SUCCESS;
ip = i;
port = p;
srs_freep(listener);
listener = new SrsTcpListener(this, ip, port);
if ((ret = listener->listen()) != ERROR_SUCCESS) {
srs_error("tcp listen failed. ret=%d", ret);
return ret;
}
srs_info("listen thread current_cid=%d, "
"listen at port=%d, type=%d, fd=%d started success, ep=%s:%d",
_srs_context->get_id(), p, type, listener->fd(), i.c_str(), p);
srs_trace("%s listen at tcp://%s:%d, fd=%d", srs_listener_type2string(type).c_str(), ip.c_str(), port, listener->fd());
return ret;
}
这里会启动一个SrsTcpListener来监听,而SrsTcpListener内部会创建并启动一个SrsReusableThread:
SrsTcpListener::SrsTcpListener(ISrsTcpHandler* h, string i, int p)
{
handler = h;
ip = i;
port = p;
_fd = -1;
_stfd = NULL;
pthread = new SrsReusableThread("tcp", this);
}
而SrsReusableThread内部会创建一个SrsThread,这个是最近的协程封装,使用它时,我们需要给它传递一个具体的handler对象,使得这个协程与具体的处理解耦,协程内部会循环调用handler的cycle()处理,而这里的cycle就是:
int SrsTcpListener::cycle()
{
int ret = ERROR_SUCCESS;
st_netfd_t client_stfd = st_accept(_stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);
if(client_stfd == NULL){
// ignore error.
if (errno != EINTR) {
srs_error("ignore accept thread stoppped for accept client error");
}
return ret;
}
srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd));
if ((ret = handler->on_tcp_client(client_stfd)) != ERROR_SUCCESS) {
srs_warn("accept client error. ret=%d", ret);
return ret;
}
return ret;
}
之后,当收到请求后,调用on_tcp_client处理,这个又通过SrsStreamListener::on_tcp_client-->SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd),最终传递给SrsServer处理
而SrsServer将其封装成一个SrsRtmpConn对象,调用其start方法,执行rtmp连接的处理流程,连接处理流程包括了信令处理及音视频处理两部分,信令处理在后面一篇文章再详说。
网友评论