zoukankan      html  css  js  c++  java
  • live555 RTSPClient类和RTSPServer类

    //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 CSeq: %s %sPublic: %s ",     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] == '')

       // 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))

  • 相关阅读:
    使用air16sdk打包ipa报错
    笔试题目
    网络编程Socket之UDP
    网络编程Socket之TCP
    Spring的HelloWorld
    一起学makefile
    使用Eclipse创建Hibernate工程
    log4j日志输出使用教程
    监听tomcat服务器启动/关闭并从配置文件中读取参数进行初始化
    java加载配置文件
  • 原文地址:https://www.cnblogs.com/huanchao/p/3479531.html
Copyright © 2011-2022 走看看