SRS学习笔记9-rtmp监听线程创建推流线程的过程分析-gdb调试
来源:互联网 发布:360度全景图制作 js 编辑:程序博客网 时间:2024/05/16 14:44
原文:http://www.cnblogs.com/yan-shi-yi/p/6845498.html
SRS学习笔记9-rtmp监听线程创建推流线程的过程分析
先用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 ?? ()
阅读全文
0 0
- SRS学习笔记9-rtmp监听线程创建推流线程的过程分析-gdb调试
- 学习SRS(SimpleRtmpServer)--推流+直播rtmp+直播hls
- gdb调试过程学习
- srs epoll监听连接过程
- SRS 代码分析【RTMP连接请求响应】
- SRS 代码分析【RTMP信息play/publish】
- SRS 代码分析【RTMP握手实现】
- SRS 代码分析【RTMP Chunck数据读取】
- SRS 代码分析【RTMP Chunck数据发送】
- gdb调试学习笔记
- srs rtmp
- RTMP协议分析及推流过程
- 【GDB调试学习笔记】GDB调试入门
- srs代码学习(8)--rtmp发送
- 通过gdb调试分析Linux内核的启动过程
- 《软件调试的艺术》学习笔记——GDB使用技巧摘要(4)——Pthread线程调试
- 《软件调试的艺术》学习笔记——GDB使用技巧摘要——Pthread线程调试
- RTMP SRS源与边界的实现
- 面试总结(二)
- ViewPager无限轮播
- Remove Duplicates from Sorted List II leetcode java
- POJ
- JS基础语法(一)
- SRS学习笔记9-rtmp监听线程创建推流线程的过程分析-gdb调试
- LINUX配置过程记录
- dfs序
- redmine-java-api的使用方法简介
- 面试总结(三)
- 关于百度之星初赛B的A题Chess
- 矩阵相关(研究总结,矩阵,矩阵快速幂)
- JAVA—容器类
- 【笔记】看"你的知识管理需要管理"有感, 补思维导图