先用gdb查看大致流程

1. rtmp监听线程创建推流线程的过程分析

gdb ./objs/srs

set args -c ./conf/rtmp.conf

b srs_app_listener.cpp:266

r

复制代码
 1 int SrsTcpListener::cycle()
 2 {
 3     int ret = ERROR_SUCCESS;
 4     
 5     st_netfd_t client_stfd = st_accept(_stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);
 6   
 7     if(client_stfd == NULL){
 8         // ignore error.
 9         if (errno != EINTR) {
10             srs_error("ignore accept thread stoppped for accept client error");
11         }
12         return ret;
13     }
14     srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd));
15     
16     if ((ret = handler->on_tcp_client(client_stfd)) != ERROR_SUCCESS) {
17         srs_warn("accept client error. ret=%d", ret);
18         return ret;
19     }
20     
21     return ret;
22 }
复制代码

这个函数将accept的client_stfd交给 ISrsTcpHandler去处理

在此处是 SrsStreamListener::on_tcp_client (this=0x8f2f80, stfd=0x8f4b70) at src/app/srs_app_server.cpp:169

 

在上面代码的第七行下断点

开启推流,断下

执行bt

复制代码
#0  SrsTcpListener::cycle (this=0x8f2fe0) at src/app/srs_app_listener.cpp:266
#1  0x00000000004ada7d in SrsReusableThread::cycle (this=0x8f3020) at src/app/srs_app_thread.cpp:452
#2  0x00000000004ace3b in internal::SrsThread::thread_cycle (this=0x8f3040) at src/app/srs_app_thread.cpp:207
#3  0x00000000004ad049 in internal::SrsThread::thread_fun (arg=0x8f3040) at src/app/srs_app_thread.cpp:245
#4  0x0000000000535371 in _st_thread_main () at sched.c:327
#5  0x0000000000535ae1 in st_thread_create (start=0x915000, arg=0x3e8, joinable=32767, stk_size=-150456151) at sched.c:591
#6  0x000000000001ff40 in ?? ()
#7  0x0000000000000000 in ?? ()
复制代码

 SrsStreamListener::on_tcp_client 代码,简单的交给SrsServer类去处理

复制代码
// SrsStreamListener改名为SrsRtmpListener更合适一些
// 还有SrsRtspListener,SrsHttpFlvListener,SrsUdpStreamListener等
int SrsStreamListener::on_tcp_client(st_netfd_t stfd)
{

    int ret = ERROR_SUCCESS;
    
    if ((ret = server->accept_client(type, stfd)) != ERROR_SUCCESS) {
        srs_warn("accept client error. ret=%d", ret);
        return ret;
    }

    return ret;
}
复制代码

type定义为

复制代码
std::string srs_listener_type2string(SrsListenerType type) 
{
    switch (type) {
    case SrsListenerRtmpStream:
        return "RTMP";
    case SrsListenerHttpApi:
        return "HTTP-API";
    case SrsListenerHttpStream:
        return "HTTP-Server";
    case SrsListenerMpegTsOverUdp:
        return "MPEG-TS over UDP";
    case SrsListenerRtsp:
        return "RTSP";
    case SrsListenerFlv:
        return "HTTP-FLV";
    default:
        return "UNKONWN";
    }
}
复制代码

此处为RTMP

在SrsStreamListener::SrsStreamListener处下断点

b SrsStreamListener::SrsStreamListener

断下后

bt

复制代码
#0  SrsStreamListener::SrsStreamListener (this=0x8f2f80, svr=0x8d53e0, t=SrsListenerRtmpStream, __in_chrg=out>, __vtt_parm=out>)
    at src/app/srs_app_server.cpp:133
#1  0x00000000004778c2 in SrsServer::listen_rtmp (this=0x8d53e0) at src/app/srs_app_server.cpp:1082
#2  0x0000000000475866 in SrsServer::listen (this=0x8d53e0) at src/app/srs_app_server.cpp:743
#3  0x000000000053480b in run_master () at src/main/srs_main_server.cpp:398
#4  0x000000000053442b in run () at src/main/srs_main_server.cpp:341
#5  0x00000000005343a9 in main (argc=3, argv=0x7fffffffe618) at src/main/srs_main_server.cpp:334
复制代码

可以看到 t=SrsListenerRtmpStream,最终处理rtmp client 连接的是

SrsServer::accept_client
复制代码
int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
{
    int ret = ERROR_SUCCESS;
    
    int fd = st_netfd_fileno(client_stfd);
    
    int max_connections = _srs_config->get_max_connections();
    if ((int)conns.size() >= max_connections) {
        srs_error("exceed the max connections, drop client: "
            "clients=%d, max=%d, fd=%d", (int)conns.size(), max_connections, fd);
            
        srs_close_stfd(client_stfd);
        
        return ret;
    }
    
    // avoid fd leak when fork.
    // @see https://github.com/ossrs/srs/issues/518
    if (true) {
        int val;
        if ((val = fcntl(fd, F_GETFD, 0)) < 0) {
            ret = ERROR_SYSTEM_PID_GET_FILE_INFO;
            srs_error("fnctl F_GETFD error! fd=%d. ret=%#x", fd, ret);
            srs_close_stfd(client_stfd);
            return ret;
        }
        val |= FD_CLOEXEC;
        if (fcntl(fd, F_SETFD, val) < 0) {
            ret = ERROR_SYSTEM_PID_SET_FILE_INFO;
            srs_error("fcntl F_SETFD error! fd=%d ret=%#x", fd, ret);
            srs_close_stfd(client_stfd);
            return ret;
        }
    }
    
    SrsConnection* conn = NULL;
    if (type == SrsListenerRtmpStream) {
        conn = new SrsRtmpConn(this, client_stfd);
    } else if (type == SrsListenerHttpApi) {
#ifdef SRS_AUTO_HTTP_API
        conn = new SrsHttpApi(this, client_stfd, http_api_mux);
#else
        srs_warn("close http client for server not support http-api");
        srs_close_stfd(client_stfd);
        return ret;
#endif
    } else if (type == SrsListenerHttpStream) {
#ifdef SRS_AUTO_HTTP_SERVER
        conn = new SrsResponseOnlyHttpConn(this, client_stfd, http_server);
#else
        srs_warn("close http client for server not support http-server");
        srs_close_stfd(client_stfd);
        return ret;
#endif
    } else {
        // TODO: FIXME: handler others
    }
    srs_assert(conn);
    
    // directly enqueue, the cycle thread will remove the client.
    conns.push_back(conn);
    srs_verbose("add conn to vector.");
    
    // cycle will start process thread and when finished remove the client.
    // @remark never use the conn, for it maybe destroyed.
    if ((ret = conn->start()) != ERROR_SUCCESS) {
        return ret;
    }
    srs_verbose("conn started success.");

    srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret);
    
    return ret;
}
复制代码

b SrsServer::accept_client

复制代码
int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
{
    int ret = ERROR_SUCCESS;
    
    int fd = st_netfd_fileno(client_stfd);
    // 成员变量 conns定义为 std::vector conns;
// 判断有没有超出配置里面的max_connections限制,否则直接关闭套接字
  int max_connections = _srs_config->get_max_connections();
    if ((int)conns.size() >= max_connections) {
        srs_error("exceed the max connections, drop client: "
            "clients=%d, max=%d, fd=%d", (int)conns.size(), max_connections, fd);
            
        srs_close_stfd(client_stfd);
        
        return ret;
    }
    
    // avoid fd leak when fork.
    // @see https://github.com/ossrs/srs/issues/518
    if (true) {
        int val;
        if ((val = fcntl(fd, F_GETFD, 0)) < 0) {
            ret = ERROR_SYSTEM_PID_GET_FILE_INFO;
            srs_error("fnctl F_GETFD error! fd=%d. ret=%#x", fd, ret);
            srs_close_stfd(client_stfd);
            return ret;
        }
        val |= FD_CLOEXEC;
        if (fcntl(fd, F_SETFD, val) < 0) {
            ret = ERROR_SYSTEM_PID_SET_FILE_INFO;
            srs_error("fcntl F_SETFD error! fd=%d ret=%#x", fd, ret);
            srs_close_stfd(client_stfd);
            return ret;
        }
    }
    // FD_CLOEXEC 标志和文件句柄泄漏参考
//http://blog.csdn.net/ustc_dylan/article/details/6930189 
// http://blog.csdn.net/chrisniu1984/article/details/7050663

// 根据不同的type,创建不同SrsConnection类,rtmp流为 SrsRtmpConn
    SrsConnection* conn = NULL;
    if (type == SrsListenerRtmpStream) {
        conn = new SrsRtmpConn(this, client_stfd);
    } else if (type == SrsListenerHttpApi) {
#ifdef SRS_AUTO_HTTP_API
        conn = new SrsHttpApi(this, client_stfd, http_api_mux);
#else
        srs_warn("close http client for server not support http-api");
        srs_close_stfd(client_stfd);
        return ret;
#endif
    } else if (type == SrsListenerHttpStream) {
#ifdef SRS_AUTO_HTTP_SERVER
        conn = new SrsResponseOnlyHttpConn(this, client_stfd, http_server);
#else
        srs_warn("close http client for server not support http-server");
        srs_close_stfd(client_stfd);
        return ret;
#endif
    } else {
        // TODO: FIXME: handler others
    }
    srs_assert(conn);
    
    // directly enqueue, the cycle thread will remove the client.
    conns.push_back(conn);
    srs_verbose("add conn to vector.");
    // 开启st线程处理这个连接
    // cycle will start process thread and when finished remove the client.
    // @remark never use the conn, for it maybe destroyed.
    if ((ret = conn->start()) != ERROR_SUCCESS) {
        return ret;
    }
    srs_verbose("conn started success.");

    srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret);
    
    return ret;
}
复制代码

bt 输出

复制代码
#0  SrsServer::accept_client (this=0x8d53e0, type=SrsListenerRtmpStream, client_stfd=0x8f4b70) at src/app/srs_app_server.cpp:1241
#1  0x0000000000472150 in SrsStreamListener::on_tcp_client (this=0x8f2f80, stfd=0x8f4b70) at src/app/srs_app_server.cpp:171
#2  0x000000000052cb49 in SrsTcpListener::cycle (this=0x8f2fe0) at src/app/srs_app_listener.cpp:275
#3  0x00000000004ada7d in SrsReusableThread::cycle (this=0x8f3020) at src/app/srs_app_thread.cpp:452
#4  0x00000000004ace3b in internal::SrsThread::thread_cycle (this=0x8f3040) at src/app/srs_app_thread.cpp:207
#5  0x00000000004ad049 in internal::SrsThread::thread_fun (arg=0x8f3040) at src/app/srs_app_thread.cpp:245
#6  0x0000000000535371 in _st_thread_main () at sched.c:327
#7  0x0000000000535ae1 in st_thread_create (start=0x915000, arg=0x3e8, joinable=32767, stk_size=-150456151) at sched.c:591
#8  0x000000000001ff40 in ?? ()
#9  0x0000000000000000 in ?? ()
复制代码