日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

srs代码学习(1)--listen建立过程

發布時間:2024/2/28 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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;??
  • ??????
  • ????//?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;??
  • }??


  • 這個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){??
  • ????????//?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;??
  • }??
  • 原來是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建立过程的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。