上一篇博客說道,live555服務端main函數做的最后一件事就是調用如下代碼陷入死循環:
env->taskScheduler().doEventLoop(); // does not return
那么這個doEventLoop是什么樣的呢?如下:
void BasicTaskScheduler0::doEventLoop(char* watchVariable) { // Repeatedly loop, handling readble sockets and timed events: while (1) { if (watchVariable != NULL && *watchVariable != 0) break; SingleStep(); } }
就是不停地調用SingleStep()這個函數,SingleStep函數中代碼比較多,我下面僅截取關鍵代碼,首先是使用selet陷入阻塞,等待事件發生:
int selectResult = select(fMaxNumSockets, &readSet, &writeSet, &exceptionSet, &tv_timeToDelay);
返回值后之后會對所有的socket進行遍歷,找到是哪個socket發生了事件:
while ((handler = iter.next()) != NULL) { int sock = handler->socketNum; // alias int resultConditionSet = 0; if (FD_ISSET(sock, &readSet) && FD_ISSET(sock, &fReadSet)/*sanity check*/) resultConditionSet |= SOCKET_READABLE; if (FD_ISSET(sock, &writeSet) && FD_ISSET(sock, &fWriteSet)/*sanity check*/) resultConditionSet |= SOCKET_WRITABLE; if (FD_ISSET(sock, &exceptionSet) && FD_ISSET(sock, &fExceptionSet)/*sanity check*/) resultConditionSet |= SOCKET_EXCEPTION; if ((resultConditionSet&handler->conditionSet) != 0 && handler->handlerProc != NULL) { fLastHandledSocketNum = sock; // Note: we set "fLastHandledSocketNum" before calling the handler, // in case the handler calls "doEventLoop()" reentrantly. (*handler->handlerProc)(handler->clientData, resultConditionSet); break; } } if (handler == NULL && fLastHandledSocketNum >= 0) { // We didn't call a handler, but we didn't get to check all of them, // so try again from the beginning: iter.reset(); while ((handler = iter.next()) != NULL) { int sock = handler->socketNum; // alias int resultConditionSet = 0; if (FD_ISSET(sock, &readSet) && FD_ISSET(sock, &fReadSet)/*sanity check*/) resultConditionSet |= SOCKET_READABLE; if (FD_ISSET(sock, &writeSet) && FD_ISSET(sock, &fWriteSet)/*sanity check*/) resultConditionSet |= SOCKET_WRITABLE; if (FD_ISSET(sock, &exceptionSet) && FD_ISSET(sock, &fExceptionSet)/*sanity check*/) resultConditionSet |= SOCKET_EXCEPTION; if ((resultConditionSet&handler->conditionSet) != 0 && handler->handlerProc != NULL) { fLastHandledSocketNum = sock; // Note: we set "fLastHandledSocketNum" before calling the handler, // in case the handler calls "doEventLoop()" reentrantly. (*handler->handlerProc)(handler->clientData, resultConditionSet); break; } } if (handler == NULL) fLastHandledSocketNum = -1;//because we didn't call a handler }
當找到相應的的socket的時候,調用的是(*handler->handlerProc)這個函數,這個函數是什么呢?在上一篇博客里講過,其實這個函數就是我們用turnOnBackgroundReadHandling()和相應socket綁定的函數,那么相對於一個server socket,綁定的就是incomingConnectionHandlerRTSP,主要功能是接受連接,創建新會話。如果是一個處理單個客戶端的socket,那它綁定的就是incomingRequestHandler(),也就是負責從socket里讀出數據,然后使用函數handleRequstBytes()對數據進行處理。
handler類型是HandlerDescriptor,這個類的定義是:
class HandlerDescriptor { HandlerDescriptor(HandlerDescriptor* nextHandler); virtual ~HandlerDescriptor(); public: int socketNum; int conditionSet; TaskScheduler::BackgroundHandlerProc* handlerProc; void* clientData; private: // Descriptors are linked together in a doubly-linked list: friend class HandlerSet; friend class HandlerIterator; HandlerDescriptor* fNextHandler; HandlerDescriptor* fPrevHandler; };
這個類存儲了select監控的socket的狀況和相關參數。其中:
TaskScheduler::BackgroundHandlerProc* handlerProc;
就是當這個socket發生事件時所需要調用的函數。
