生活随笔
收集整理的這篇文章主要介紹了
srs代码学习(1)--listen建立过程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
srs的服務偵聽的建立過程。
以rtmp服務為例 srs服務偵聽的建立依靠從上到下的三個類。分別是
SrsServer ?
SrsStreamListener ?
SrsTcpListener
端口偵聽過程為
1)main函數中調用全局變量_srs_server的??listen()函數
[cpp]?view plain?copy ? ?
if?((ret?=?_srs_server->listen())?!=?ERROR_SUCCESS)?{?? ????????return?ret;?? ????}??
[cpp]?view plain?copy ? ?
在SrsServer的listen()函數如下??
[cpp]?view plain?copy ? ?
<pre?name="code"?class="cpp">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;?? }??
[cpp]?view plain?copy ? ?
listen_rtmp()會建立一個rtmp的steamlistener??
[cpp]?view plain?copy ? ?
<pre?name="code"?class="cpp">int?SrsServer::listen_rtmp()?? {?? ????int?ret?=?ERROR_SUCCESS;?? ?????? ?????? ????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;?? }??
這個streamlistener并不是真正的底層監聽層。只是一個業務封裝層。其類的繼承順序如下
在整個代碼中,和其相識的類有SrsRtspListener ?SrsHttpFlvListener兩個類。這種類的主要作用是在底層鏈接建立有。給不同的上層放回鏈接信息。
代碼走到這一步,偵聽的socket還么米有建立起來,看SrsStreamListener的listen()函數
[cpp]?view plain?copy ? ?
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;?? }??
在這段代碼里面。創建了真正的底層監聽類
[cpp]?view plain?copy ? ?
listener?=?new?SrsTcpListener(this,?ip,?port);??
然后調用其listen()函數。代碼如下
[cpp]?view plain?copy ? ?
int?SrsTcpListener::listen()?? {?? ????int?ret?=?ERROR_SUCCESS;?? ?????? ????if?((_fd?=?socket(AF_INET,?SOCK_STREAM,?0))?==?-1)?{?? ????????ret?=?ERROR_SOCKET_CREATE;?? ????????srs_error("create?linux?socket?error.?port=%d,?ret=%d",?port,?ret);?? ????????return?ret;?? ????}?? ????srs_verbose("create?linux?socket?success.?port=%d,?fd=%d",?port,?_fd);?? ?????? ????int?reuse_socket?=?1;?? ????if?(setsockopt(_fd,?SOL_SOCKET,?SO_REUSEADDR,?&reuse_socket,?sizeof(int))?==?-1)?{?? ????????ret?=?ERROR_SOCKET_SETREUSE;?? ????????srs_error("setsockopt?reuse-addr?error.?port=%d,?ret=%d",?port,?ret);?? ????????return?ret;?? ????}?? ????srs_verbose("setsockopt?reuse-addr?success.?port=%d,?fd=%d",?port,?_fd);?? ?????? ????sockaddr_in?addr;?? ????addr.sin_family?=?AF_INET;?? ????addr.sin_port?=?htons(port);?? ????addr.sin_addr.s_addr?=?inet_addr(ip.c_str());?? ????if?(bind(_fd,?(const?sockaddr*)&addr,?sizeof(sockaddr_in))?==?-1)?{?? ????????ret?=?ERROR_SOCKET_BIND;?? ????????srs_error("bind?socket?error.?ep=%s:%d,?ret=%d",?ip.c_str(),?port,?ret);?? ????????return?ret;?? ????}?? ????srs_verbose("bind?socket?success.?ep=%s:%d,?fd=%d",?ip.c_str(),?port,?_fd);?? ?????? ????if?(::listen(_fd,?SERVER_LISTEN_BACKLOG)?==?-1)?{?? ????????ret?=?ERROR_SOCKET_LISTEN;?? ????????srs_error("listen?socket?error.?ep=%s:%d,?ret=%d",?ip.c_str(),?port,?ret);?? ????????return?ret;?? ????}?? ????srs_verbose("listen?socket?success.?ep=%s:%d,?fd=%d",?ip.c_str(),?port,?_fd);?? ?????? ????if?((_stfd?=?st_netfd_open_socket(_fd))?==?NULL){?? ????????ret?=?ERROR_ST_OPEN_SOCKET;?? ????????srs_error("st_netfd_open_socket?open?socket?failed.?ep=%s:%d,?ret=%d",?ip.c_str(),?port,?ret);?? ????????return?ret;?? ????}?? ????srs_verbose("st?open?socket?success.?ep=%s:%d,?fd=%d",?ip.c_str(),?port,?_fd);?? ?????? ????if?((ret?=?pthread->start())?!=?ERROR_SUCCESS)?{?? ????????srs_error("st_thread_create?listen?thread?error.?ep=%s:%d,?ret=%d",?ip.c_str(),?port,?ret);?? ????????return?ret;?? ????}?? ????srs_verbose("create?st?listen?thread?success,?ep=%s:%d",?ip.c_str(),?port);?? ?????? ????return?ret;?? }??
到此,rtmp的監聽端口就建立起來了。
在仔細看SrsTcpListener類。繼承關系如下
這個類中很有趣的有了個線程類SrsReusableThread* pthread,這個線程是什么時候建立的?答案是在構造函數中
[cpp]?view plain?copy ? ?
SrsTcpListener::SrsTcpListener(ISrsTcpHandler*?h,?string?i,?int?p)?? {?? ????handler?=?h;?? ????ip?=?i;?? ????port?=?p;?? ?? ????_fd?=?-1;?? ????_stfd?=?NULL;?? ?? ????pthread?=?new?SrsReusableThread("tcp",?this);?? }??
這個類的作用是什么呢?首先我們發現,
SrsTcpListener 這個類繼承了一個線程回調接口ISrsReusableThreadHandler。這個說明可以擁有可以在線程中運行的能力
觀察線程類的結構
很奇怪,SrsReusableThread竟然也繼承了一個handler類。這就表示。這個類還是一個封裝類,并不是底層的真正的線程類。果然我們發現了其一個變量?internal::SrsThread* pthread,這個應該靠近點底層了吧。先放下不講。我們是來追這個線程類也我的業務類啥關系的。這時另外一個有意思的變量ISrsReusableThreadHandler* handler,還記得
SrsTcpListener 類么,其有一個ISrsReusableThreadHandler的接口。通過這個接口,把線程和業務鏈接起來。看看其cycle()函數
[cpp]?view plain?copy ? ?
int?SrsReusableThread::cycle()?? {?? ????return?handler->cycle();?? }??
這個是線程這執行函數。它會調用上層類,具體到我們的例子里,就是
SrsTcpListener 的cycle().看看是什么
[cpp]?view plain?copy ? ?
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){?? ?????????? ????????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;?? }??
原來是accept函數。在有鏈接后直接上調給上層,具體來講就是
SrsStreamListener類的
on_tcp_client()函數
[cpp]?view plain?copy ? ?
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;?? }??
歐耶,這下調用到最上層去了。server里,建立一個鏈接。
到現在還有兩個問題要搞明白:
1)srs的線程模型
2)如何管理各個鏈接。
這個下一次在摸索
http://blog.csdn.NET/ddr77/article/details/52314210
總結
以上是生活随笔為你收集整理的srs代码学习(1)--listen建立过程的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。