zoukankan      html  css  js  c++  java
  • 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发生事件时所需要调用的函数。

     

       

  • 相关阅读:
    a标签实现文件下载
    $(obj).index(this)与$(this).index()异同讲解
    jquery attr处理checkbox / select 等表单元素时只能使用一次的坑
    多元素浮动高度不一致导致的参差不齐问题解决方案
    jQuery插件 -- 图片随页面滚动fixed
    setTimeout异步加载
    jquery中html、text、val回调函数
    如何使文件在django自动执行
    Django如何从Model中获取字段名称——verbose_name
    Django在根据models生成数据库表时报错
  • 原文地址:https://www.cnblogs.com/dchipnau/p/5458979.html
Copyright © 2011-2022 走看看