上一篇博客说道,live555服务端main函数做的最后一件事就是调用如下代码陷入死循环:

env->taskScheduler().doEventLoop(); // does not return

那么这个doEventLoop是什么样的呢?如下:

void BasicTaskScheduler0::doEventLoop(char* watchVariable) {
// Repeatedly loop, handling readble sockets and timed events:
while () {
if (watchVariable != NULL && *watchVariable != ) 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 = ;
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) != && 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 >= ) {
// 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 = ;
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) != && 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 = -;//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发生事件时所需要调用的函数。

2.live555源码分析----服务端doEventLoop()函数分析的更多相关文章

  1. Netty源码解析---服务端启动

    Netty源码解析---服务端启动 一个简单的服务端代码: public class SimpleServer { public static void main(String[] args) { N ...

  2. zookeeper源码之服务端数据库管理中心

    负责管理ZooKeeper整个数据.主要管理树结构数据.session数据.持久化管理. 类图 ZKDatabase ZooKeeper数据管理门户类,底层通过DataTree来管理树结构,通过Fil ...

  3. zookeeper源码之服务端

    zookeeper服务端主要包括一下几个模块:     1.启动模块. 2.核心执行模块 3.数据管理模块. 启动模块 读取配置文件,启动程序.详见:zookeeper源码之服务端启动模块. 核心执行 ...

  4. Netty 源码学习——服务端流程分析

    在上一篇我们已经介绍了客户端的流程分析,我们已经对启动已经大体上有了一定的认识,现在我们继续看对服务端的流程来看一看到底有什么区别. 服务端代码 public class NioServer { pr ...

  5. Netty源码解析 -- 服务端启动过程

    本文通过阅读Netty源码,解析Netty服务端启动过程. 源码分析基于Netty 4.1 Netty是一个高性能的网络通信框架,支持NIO,OIO等多种IO模式.通常,我们都是使用NIO模式,该系列 ...

  6. kbengine mmo源码(完整服务端源码+资源+完整客户端源码)

      本项目作为kbengine服务端引擎的客户端演示而写 更新kbengine插件库(https://github.com/kbengine/kbengine_unity3d_plugins):    ...

  7. Nacos源码系列—服务端那些事儿

    点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 项目源码地址:公众号回复 nacos,即可免费获取源码 前言 在上节课中,我们讲解了客户端注册服 ...

  8. Hadoop RPC源码阅读-服务端Server

    Hadoop版本Hadoop2.6 RPC主要分为3个部分:(1)交互协议 (2)客户端(3)服务端 (3)服务端 RPC服务端的实例代码: public class Starter { public ...

  9. zookeeper源码之服务端核心执行模块

    服务端核心执行模块包括一下几个部分 1.leader选举. 2.

随机推荐

  1. str.replace替换变量名的字符串

    网易云课堂该课程链接地址 https://study.163.com/course/courseMain.htm?share=2&shareId=400000000398149&cou ...

  2. HTML+CSS编写五环居中案例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. django学习问题集

    case 1: python manage.py migrate时报错:django.core.exceptions.ImproperlyConfigured: Error loading MySQL ...

  4. vue方法中传递dom对象示例

    <div id="app"> <input type="text" v-on:keyup="onlyNum($event)" ...

  5. 生成pcf文件

    import os import datetime import hashlib def checksum(filename): with open(filename, mode='rb') as f ...

  6. Redis常用运维命令

    1.启动命令 按照我其他博客的按照方法,启动命令为/etc/init.d/redis_6379 start 2.查看内存统计信息 [root@bogon ~]# redis-cli > info ...

  7. C# web项目乱码问题解决

    在 web.config 文件中添加代码  <globalization requestEncoding="GB2312" responseEncoding="GB ...

  8. 头部文件jq嵌入笔记

    var headHtml = '<div class="container">' + '<div class="navbar-header"& ...

  9. LeetCode 1021. 删除最外层的括号(Remove Outermost Parentheses)

    1021. 删除最外层的括号 1021. Remove Outermost Parentheses 题目描述 有效括号字符串为空 ("")."(" + A + ...

  10. java的线程池的使用

    1.线程池的创建 1.首先创建一个类,然后实现Runnable接口 public class ExectorTest implements Runnable {} 2.首先声明一个线程池的全局变量 p ...