程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> live555 RTSPClient類和RTSPServer類

live555 RTSPClient類和RTSPServer類

編輯:C++入門知識

//1.DynamicRTSPServer():DynamicRTSPServer.cpp

//    |---RTSPServerSupportingHTTPStreaming():RTSPServerSupportingHTTPStreaming.cpp

//2.createNew():DynamicRTSPServer.cpp

//    |---setUpOurSocket():RTSPServer.cpp

//        |---setupStreamSocket():GroupsockHelper.cpp

//            |---createSocket():同上

//            |---MAKE_SOCKADDR_IN():初始化struct sockaddr_in,GroupsockHelper.h,

//            |---bind()

//                |---sock = socket(AF_INET, type|SOCK_CLOEXEC, 0);

//    |---DynamicRTSPServer():DynamicRTSPServer.cpp

//        |---RTSPServerSupportingHTTPStreaming():RTSPServerSupportingHTTPStreaming.cpp 3.RTSPServerSupportingHTTPStreaming():RTSPServerSupportingHTTPStreaming.cpp

    |---RTSPServer():RTSPServer.cpp

4.RTSPServer():RTSPServer.cpp

    |--- Medium():Media.cpp

    |---fRTSPServerPort():

    |---fRTSPServerSocket():

    |---fHTTPServerSocket():

    |---fHTTPServerPort():

    |---fServerMediaSessions():

    |---fClientConnections():

    |---fClientSessions():

    |---fPendingRegisterRequests():

    上述均為初始化

    |---env.taskScheduler().turnOnBackgroundReadHandling(fRTSPServerSocket,                                      (TaskScheduler::BackgroundHandlerProc*)&incomingConnectionHandlerRTSP, this);

    把連接處理函數句柄(RTSPServer::incomingConnectionHandler)和socket句柄傳給任務調度器(taskScheduler)     任務調度器把socket句柄放入後面select調用中用到的socket句柄集(fReadSet)中,

    同時將socket句柄和incomingConnectionHandler句柄關聯起來。

    接著,主程序開始進入任務調度器的主循環(doEventLoop),在主循環中調用系統函數select阻塞,等待網絡連接。 5.incomingConnectionHandler():RTSPServer.cpp

    |---clientSocket = accept()

6.turnOnBackgroundReadHandling():UsageEnvironment.h

    |---setBackgroundHandling():(virtual)

7.RTSPServer.cpp中有各種消息處理函數:handleCmd_SETUP(),handleCmd_TEARDOWN(),handleCmd_PLAY(),   handleCmd_PAUSE(),handleCmd_GET_PARAMETER(),handleCmd_SET_PARAMETER().

8.Medium():Media.cpp

    |---

9.RTSPClient類:

10.createNew():RTSPClient.cpp

    |---RTSPClient():構造函數

11.RTSPClient():

    |---Medium():

    |---fVerbosityLevel():

    |---fServerAddress():

    |---fTunnelOverHTTPPortNum():

    |---fInputSocketNum():

    |---fLastSessionId():

    以上皆為初始化

    |---setBaseURL(rtspURL):

    |---envir().taskScheduler().setBackgroundHandling(fInputSocketNum, SOCKET_READABLE|SOCKET_EXCEPTION,    (TaskScheduler::BackgroundHandlerProc*&incomingDataHandler, this);

12.incomingDataHandler():RTSPClient.cpp

    |---incomingDataHandler1():

        |---readSocket():GroupsockHelper.cpp

            |---recvfrom()

        |---handleResponseBytes():

            |---RequestQueue requestQueue(fRequestsAwaitingResponse);

            |---request = requestQueue.dequeue()

            |---request = fRequestsAwaitingResponse.dequeue()

            |---handleSETUPResponse()

            |---handlePLAYResponse()

            |---handleTEARDOWNResponse()

            |---handleGET_PARAMETERResponse()

13.handlePLAYResponse():RTSPClient.cpp

    |---MediaSubsessionIterator iter(session):

    將會話放入iter()返回子會話迭代器

    |---while ((subsession = iter.next()) != NULL):

    輪詢所有的子會話

    |---if (subsession->rtpSource() != NULL) subsession->rtpSource()->enableRTCPReports() = True;

    // start sending RTCP "RR"s now

    handlePLAYResponse()將會話和子會話都查找一遍,調用以上三步;

     // The command was on a subsession

14.sendRequest(RequestRecord* request):RTSPClient.cpp

    發送請求,請求統一封裝在RequestRecord

    |---if (!fRequestsAwaitingConnection.isEmpty())

    // A connection is currently pending (with at least one enqueued request).  Enqueue this request also       判斷連接是否存在,若存在,則請求入隊,然後返回一個序列號,否則創建一個連接:

    |---connectResult = openConnection()

     // Construct and send the command:

    |---authenticatorStr = createAuthenticatorString()

    |---send()

    // The command send succeeded, so enqueue the request record, so that its response (when it comes) can be handled.

    如果發送成功就將請求記錄入隊,這樣,當請求到來時可以被處理

    |---cseq = request->cseq()

    最後返回一個序列號

15.lookupByName()

    查找sourceName指定的RTSPClient

    |---if (!Medium::lookupByName(env, instanceName, medium)) return False;

    |---!medium->isRTSPClient()

    |---resultClient = (RTSPClient*)medium;return True;

16.RTSPClient.cpp的其他函數:

    |---reset()

    重置RTSPClient,1、關閉socket;2、重置responseBuffer的指示變量;3、清除分BaseURL等

    |---setBaseURL(char const* url)

    設置請求的URL信息fBaseURL

    |---RTSPClient::RequestRecord::RequestRecord()

    該類封裝了請求命令,只用來保存請求的信息,如命令名稱、回調函數等:     RTSPClient::RequestRecord::RequestRecord(unsigned cseq, responseHandler* handler,       char const* absStartTime, char const* absEndTime, float scale,       MediaSession* session, MediaSubsession* subsession)     :fNext(NULL), fCSeq(cseq), fCommandName("PLAY"), fSession(session), fSubsession(subsession), fBooleanFlags(0),     fStart(0.0f), fEnd(-1.0f), fAbsStartTime(strDup(absStartTime)), fAbsEndTime(strDup(absEndTime)), fScale(scale),     fContentStr(NULL), fHandler(handler) {     }

    所有信息都在初始化時傳入,之後類為每一個信息都提供了訪問方法     |---RTSPClient::RequestQueue::RequestQueue()

    該類定義了RequestRecord的隊列,可以保存請求信息,還提供了一些工具方法如下:

    putAtHead(RequestRecord* request);

// "request" must not be NULL

    RequestRecord* findByCSeq(unsigned cseq);

    |---sendPlayCommand()

    |---sendPauseCommand()

    |---sendRecordCommand()

    |---sendTeardownCommand()

17.RTSPServer類:RTSPServer.cpp

18.createNew():RTSPServer.cpp
    |---ourSocket = setUpOurSocket(env, ourPort):RTSPServer.cpp
            |---setupStreamSocket():GroupsockHelper.cpp
                |---createSocket():GroupsockHelper.cpp
                    |---sock = socket(AF_INET, type|SOCK_CLOEXEC, 0);
             // Make sure we have a big send buffer:
            |---increaseSendBufferTo(env, ourSocket, 50*1024)
            |---getSourcePort(env, ourSocket, ourPort):RTSPServer.cpp
                |---getSourcePort0()

                    //getsockname() returns the current address to which the socket socketfd is bound,
                    //in the buffer pointed to by addr.
                    |---getsockname(socket, (struct sockaddr*)&test, &len)
                    |---resultPortNum = ntohs(test.sin_port);
                         return True;
                |---MAKE_SOCKADDR_IN():初始化struct sockaddr_in,GroupsockHelper.h,
                |---bind()
                |---port = Port(portNum);/* in host byte order */
    |---RTSPServer():構造函數

19.RTSPServer()見第四點

20.addServerMediaSession()

    將sessionName對應的serverMediaSession加入到哈希表中

    |---fServerMediaSessions->Add(sessionName, (void*)serverMediaSession) 21.removeServerMediaSession()

    從查找表中刪除"ServerMediaSession" 對象,新到來的RTSP客戶端不能再訪問他

    但是原來的RTSP客戶端會話仍然能工作。

    當所有的RTSP客戶端會話都被關閉時,"ServerMediaSession" 對象才能被刪除。

22. deleteServerMediaSession()

    相當於調用了closeAllClientSessionsForServerMediaSession()和removeServerMediaSession()。

23.class RegisterRequestRecord: public RTSPRegisterSender    RegisterRequestRecord()        |---RTSPRegisterSender()

       |---fOurServer(ourServer)

       |---fRequestId(requestId)

       |---fResponseHandler(responseHandler)

       |---ourServer.fPendingRegisterRequests->Add((char const*)this, this)

       // Add ourself to our server's 'pending REGISTER requests' table:

       將這個RTSPServer加入到REGISTER請求等待表

24.handleResponse():屬於class RegisterRequestRecord

    // The "REGISTER" request succeeded, so use the still-open RTSP socket

       to await incoming commands from the remote endpoint

    如果成功加入REGISTER請求表,創建一個RTSP socket,等待遠程連接命令

    |---grabConnection(sock, remoteAddress)

        |---grabSocket()

        |---MAKE_SOCKADDR_IN

    |---fOurServer.createNewClientConnection(sock, remoteAddress)

        |---return new RTSPClientConnection(*this, clientSocket, clientAddr)

        這是個構造函數

     // Call our (REGISTER-specific) response handler now

    |---(*fResponseHandler)(&fOurServer, fRequestId, resultCode, resultString);

25.RTSPClientConnection()

    |---fOurServer.fClientConnections->Add((char const*)this, this)

    |---envir().taskScheduler().setBackgroundHandling(fClientInputSocket, SOCKET_READABLE|SOCKET_EXCEPTION,   (TaskScheduler::BackgroundHandlerProc*)&incomingRequestHandler, this);

    把連接處理函數句柄(incomingRequestHandler)和socket句柄傳給任務調度器(taskScheduler),

    同時將socket句柄和incomingConnectionHandler句柄關聯起來。

26.registerStream()

     // Create a new "RegisterRequestRecord" that will send the "REGISTER" command.

     //(This object will automatically get deleted after we get a response to the "REGISTER" command,         or if we're deleted.)

    為發送"REGISTER"命令而創建一個"RegisterRequestRecord"對象

    當我們收到"REGISTER"命令時,這個對象會自動刪除

    |---authenticator = new Authenticator(username, password)

    |---new RegisterRequestRecord()

27.setUpOurSocket()

 |---ourSocket = setupStreamSocket(env, ourPort):GroupsockHelper.cpp

        // Call "socket()" to create a (IPv4) socket of the specified type.

        // But also set it to have the 'close on exec' property (if we can)

        |---createSocket(SOCK_STREAM):GroupsockHelper.cpp

            |---sock = socket(AF_INET, type|SOCK_CLOEXEC, 0);

        |---setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR,    (const char*)&reuseFlag, sizeof reuseFlag)

        |---#ifdef SO_REUSEPORT

            setsockopt(newSocket, SOL_SOCKET, SO_REUSEPORT,    (const char*)&reuseFlag, sizeof reuseFlag)

       |---MAKE_SOCKADDR_IN

       |---bind(newSocket, (struct sockaddr*)&name, sizeof name)

       |---if (makeNonBlocking)

              makeSocketNonBlocking(newSocket)

 |---increaseSendBufferTo(env, ourSocket, 50*1024)

    // Make sure we have a big send buffer

    保證有足夠的發送緩沖

|---listen(ourSocket, LISTEN_BACKLOG_SIZE)

    // Allow multiple simultaneous connections

    允許並發連接

    // bind() will have chosen a port for us; return it also

    bind()函數已經為我們選擇了一個端口號,我們也可以自定義

|---getSourcePort(env, ourSocket, ourPort):GroupsockHelper.cpp

        |---getSourcePort0(socket, portNum)

            分配一個端口號

            |---getsockname()

            |---resultPortNum = ntohs(test.sin_port)

28.incomingConnectionHandlerRTSP()

    |---incomingConnectionHandlerRTSP1()

        |---incomingConnectionHandler(fRTSPServerSocket)

            |---clientSocket = accept()

            |---makeSocketNonBlocking(clientSocket)

            |---increaseSendBufferTo(envir(), clientSocket, 50*1024)

29.handleCmd_OPTIONS()

    |---snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,     "RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sPublic: %s\r\n\r\n",     fCurrentCSeq, dateHeader(), fOurServer.allowedCommandNames());

30.handleCmd_GET_PARAMETER()

31.handleCmd_SET_PARAMETER()

32.handleCmd_DESCRIBE()

33.還有好幾個handleCmd函數

34.RTSPServer::RTSPClientConnection::incomingRequestHandler

    |---session->incomingRequestHandler1()

        |---bytesRead = readSocket():GroupsockHelper.cpp

            |---int bytesRead = recvfrom()

        |---handleRequestBytes(bytesRead)

35.handleRequestBytes()

    |---parseRTSPRequestString()

    // If the request included a "Session:" id, and it refers to a client session that's current ongoing, then use this

    // command to indicate 'liveness' on that client session:

    |---fOurServer.fClientSessions->Lookup(sessionIdStr)

    |---handleCmd_OPTIONS()

    |---handleCmd_GET_PARAMETER()

    |---handleCmd_SET_PARAMETER()

    |---handleCmd_DESCRIBE()

    |---if (sessionIdStr[0] == '\0')

   // No session id was present in the request.  So create a new "RTSPClientSession" object for this request.    // Choose a random (unused) 32-bit integer for the session id (it will be encoded as a 8-digit hex number).

   // (We avoid choosing session id 0, because that has a special use (by "OnDemandServerMediaSubsession").)

   如果在請求中沒有會話ID,那就為該請求創建一個新的"RTSPClientSession"對象

   u_int32_t sessionId;

   sessionId = (u_int32_t)our_random32()

    |---clientSession = fOurServer.createNewClientSession(sessionId);

 fOurServer.fClientSessions->Add(sessionIdStr, clientSession);

    // The request included a session id.  Make sure it's one that we have already set up:

    |---clientSession = (RTSPServer::RTSPClientSession*)(fOurServer.fClientSessions->Lookup(sessionIdStr));

    |---clientSession->handleCmd_SETUP() 36.RTSPServer::RTSPClientSession::RTSPClientSession()

37.RTSPServer::ServerMediaSessionIterator::ServerMediaSessionIterator()

    這個是構造函數

    |---:fOurIterator((server.fServerMediaSessions == NULL)    ? NULL : HashTable::Iterator::create(*server.fServerMediaSessions))

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved