2.live555源码分析----服务端doEventLoop()函数分析
上一篇博客说道,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发生事件时所需要调用的函数。