先用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=<optimized out>, __vtt_parm=<optimized 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<SrsConnection*> 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 ?? ()
复制代码