5.9.Webrtc线程事件处理

在前面的课程中呢,我已经向你介绍了事件处理的一些基础知识,那今天呢,我们再来看一下外边儿rtc下事件处理的基本逻辑是什么?
那首先呢,我们来看一下事件是如何协调线程工作的,那就如果这张图所展示的有两个线程,对吧?一个是限定线程,一个是工作线程。其中,工作线程呢,
在这里插入图片描述

又称为等待线程,它会因为一个事件而睡眠,直到事件发生为止。这两个线程是如何协调工作的呢?那中间儿就要有一个公共对象在外边儿tc下,这个公共对象就是non socket server或者是physical socket server。这在我们上节课中都向你做过介绍了,对吧?

那对于工作线程来说,它要等待事件就是等待。公共对象中的某个事件,那当等待这个事件的时候呢?整个线程就处于睡眠状态。也就不工作了。而对于信令线程或者说发送事件的线程来说呢,

它会主动发送一个事件给公共对象,那当公共对象收到这个事件之后呢,就会将睡眠的线程。唤醒这样呢,这个睡眠的线程就可以继续工作了,这是事件协调线程工作的一个基本的原理OK?

那下面呢,我们再来看看web rtc下是如何这个控制事件的发生的,那对于web rtc来说,它有两个。事件的发生源那第一个呢是信令线程对吧?那信令线程可以通过主动触发事件。来调用公共对象,从而呢,唤醒等待线程,
在这里插入图片描述

这是第一个触发源,那第二个触发源呢,一般看不到。它是由系统层触发的,也就是通过socket事件来触发公共对象,从而将等待线程唤起。实际上呢,这块知识点在我们前面的课程中呢,也大概向你做了一点介绍。那这张图呢,可以使你更加清楚的了解这两个事件源好,那了解了上面这些知识之后呢,下面我们就来看一下,对于等待线程,它的处理逻辑是怎样的?
在这里插入图片描述

实际这张PPT呢,我们在之前也向你做过介绍,那对于等待线程来说,它处理逻辑非常简单,就是通过一个死循环。不断的执行,那在这个执行过程中呢,主要做两件事儿,第一件事儿呢是通过get从队列中获取消息。如果此时队列中有消息,那它就会将这个消息交给dispatch,通过dispatch函数对这个消息进行处理。那如果队列中没有消息,在get函数内部会进行等待,也就是说指当前线程处于睡眠状态,

等待时间的触发。这个逻辑呢,非常的清晰,那接下来呢,我们来看一下get函数中做了什么事,
在这里插入图片描述

那对于get函数来说呢,它有两层循环,我们来看一下。它里边逻辑是怎样的?首先我们来看看,在这个大的循环里边儿,这个小的循环,它的作用是什么?那这里呢?我们第一个看到的是获得锁,

对吧?那获得这个锁的含义是什么呢?实际这个锁就是队列锁。当两个线程对同一个队列进行操作的时候,那都需要先获得这把锁之后才能对队列进行操作。对于发送消息的线程来说,它首先要获得这把锁,之后呢,才能向队列中插入消息。而对于获取数据的线程来说呢,它也要先获得这把锁之后呢,才能从堆列中取出消息。当获得这把锁之后,我们来看get函数做了哪些事啊?它首先判断这个消息队列是否为空。

那如果为空,它直接就退出这个while循环了,对吧?那退出这个循环之后,它做哪件事呢?就是调socket server的weight函数。那在weight函数中呢,就会调用事件等待API,等待事件的触发。那如果队列不为空,它就会从队列中取出这个消息,并且呢,将消息弹出队列,并从这个函数返回。那由于p message是输出参数,

所以通过它的输出参数呢?那外层就可以拿到这个消息进行进一步的处理了,也就是交由dispatch。进行消息的处理,那所以这个逻辑啊,还是非常简单的。也就是说,在大的循环里头,包括了两块儿,一块儿呢,是对队列的操作,那当队列为空的时候呢,它就进入睡眠状态。等待信号的触发,那如果有信号过来之后。

它就会继续执行,对吧?那对于wait来说,它可以设置成永久等待,也可以设置成短时等待。如果是短时等待,当超时之后。它又通过这个外部循环进入了睡眠状态,这就是外层循环,它的作用,那内层循环呢?适用于处理消息,外层循环呢?适用于处理当wait超时之后继续等待。OK,

在这里插入图片描述

那这是get函数,那这里呢?我们还要关注一下wait函数,看看wait函数里是怎么实现的?对于位的函数来说呢,不同的socket server,它的时间是不一样的,那有non socket server和physical socket server,那这里呢,我以physical socket server为例。来看一下位的函数的实现,我们只要了解了physical socket server的实现,就可以知道non socket server它是怎么做的了。好,对于physical socket server的weight函数来说呢,

它又一层循环,对吧?在这个循环里头。有一个for循环,这个for循环呢?是用于我们将socket与事件进行绑定的,也就是调用的wsa even的select这个API。对吧,这个API呢,我们在前面已经向你做过详细介绍了,那这个API不清楚的同学可以再翻一下,上面我们讲解的内容。当所有的socket都与事件绑定之后。它会调用wsa wait for multiple events,这个API那这个API实际就是对事件进行检查。

如果事件来了,它就继续执行下面的操作,如果没有事件,它就会让这个线程呢,直接在这里。进行睡眠对吧?直到事件发生为止。那我们来看一下这个函数,它几个参数,实际这几个参数呢,我们前面也做过介绍,那第一个参数呢,就是我们这个事件数组中。一共有多少个事件对吧?第二个呢?

是事件的数组,第三个是是否所有的事件都触发才唤醒这个线程?那FALSE呢,就是只要有一个时间触发了。它就唤醒了,对吧?好,再下一个参数负一就是永远等待,直到有事件发生,这个参数呢?就是time out最后一个参数呢?我们设成了。好,那再接下来啊,如果有时间触发了对于physical socket server的weight函数来说。

它要判断是哪个socket触发的事件,这个时候呢,在这个for循环中就会调用ws a。enumerate network event这个API那在这个API中呢?它会对这个事件中的所有socket进行遍历。如果他发现输出参数evs的network events,某个事件被置位了,那他就进行相应的逻辑处理。那否则呢,如果没有任何事件,它在循环遍历下一个socket,那这就是physical socket server。它的一个主要逻辑。当对于web rtc的weight实现来说呢,它里边包含了很多代码,(这就是一个很正常的select的处理流程)

这里呢,是我将一些不重要的代码简化之后,剩下的主干代码。那通过这个主干代码,我们就可以知道它真正做了什么事了,对吧?好,那现在呢?我们就将等待线程的整个逻辑向你做了介绍,首先通过get获取消息。对吧,在get内部呢,它会进行判断是否队列为空,如果队列为空或者是没有触发socket事件。那它就会调用wait函数,

最终调用wait for multiple events,这个API使线程处于睡眠状态。那当有事件来了,或者是队列不为空了,或者是发生骚位的事件了,那这个时候呢,他会从睡眠状态唤起。那唤起之后呢,就做后边的这段逻辑对吧?对这个三维的事件进行处理,或者是从队列中取出消息。一个是s时间,延安在这整个过程,我们了解之后呢,下面我们就来看一下外边tc源码,

咱们过一下这个逻辑。好,我们切换到Windows系统下,那在这里呢?首先我们要打一些断点,在哪里打呢?实际主要就是在three的点CC这个文件中,那这个文件是在哪个目录下呢?是在rtc base下边儿的rtc base,这个工程在这个工程中呢,就包含了three的点儿CC文件。好在这个文件中呢,首先我们可以搜一下。process.那实际上这个函数我们在前面的课程中也向你做过介绍,
在这里插入图片描述

对吧?当我们找到这个process之后呢,我们看一下它的实现。这就是这里。在984行。这样呢,我们就在process message这个函数中呢,设一个断点在哪设呢?就是在993行。在这个while循环这儿,我们设一个断点,这样我们就可以看到等待线程,它的处理逻辑是怎样的了,对吧?当我们将这个断点设置好之后呢?
在这里插入图片描述

我们将peer connection clan端给启动起来。继续执行。连接新的服务器。那这块我们先不管,先继续执行。我们连接一个对端。那首先呢,它会创建peer connection factory对吧?这个我们在之前都讲过,那在创建peer connection factory的时候呢?会创建几个线程?一是网络线程,二是工作线程。那当线程启动起来之后呢?这些线程呢?

就开始工作了,对于等待线程来说,那它就会跳到while循环上去。处理消息,我们继续执行好,这是它内部去创建physical socket server,对吧?在创建。physical socket server的时候呢?在它里边,会创建一个事件hev。这个事件是用于处理消息队列的。
在这里插入图片描述

那还会创建另外一个事件是socket ev这个事件呢,是用于处理socket消息的。
在这里插入图片描述

所以它一共有两个事件源,这我们都看到了,对吧?分别是。消息队列。还有socket好,我们继续执行。
在这里插入图片描述

那通过上面这段代码呢,我们就将网络线程创建好了,接下来呢,它创建工作线程对于工作线程来说呢,它使用的是n。设位的设备。好,我们进入到这个函数中。那在这个函数中呢?
在这里插入图片描述

684行,我们可以看到。对于这个线程,它使用的是non socket server,对吧?我们继续往下走。好,这时候呢,我们就将工作线程也启动起来了,那当工作线程启动的时候呢,我们可以看到之前创建的网络线程已经处于。等待状态了,我们来看一下它的调用站。那从这个调用站中呢,我们就可以知道是网络编程处于了等待状态,
在这里插入图片描述

那首先呢,我们来看一下process message(等待线程或者说是网络线程)。那在这个函数中呢?在998行,它调用了get函数对吧?那在get函数中,首先有一个well循环。也就是442行在这个while循环的下边,又有一个while循环446行在446行这个while循环里边。它首先获得队列锁对吧?451行那拿到这个锁之后呢?它会做一堆逻辑,那这一块逻辑呢?我们暂时先不管,因为它不是核心逻辑。
在这里插入图片描述

那核心逻辑是哪块呢?是467行到472行。也就是首先判断队列是否为空,如果为空就直接退出了,退出之后它就进入睡眠状态。否则的话呢,它就从队列中取出一个消息,取出这个消息,它干什么呢?取出这个消息之后,它就直接返回了,对吧?那回到上一层,就会对获取到消息进行处理。那如果没有消息,
在这里插入图片描述

它会怎么办呢?它就会调用位的函数进行等待,对吧?好,那下面呢?我们再来看看wait函数做了哪些事情?那wait函数呢?准备执行wait for multiple events这个API了。那对于这个API来说呢,它的输入参数与我们在PPT中写的是不一样的,但是它的含义是类似的。也是事件的个数,事件数组这个为就是当有事件来了之后就立马触发。不需要等待所有的事件都来。等待超时时间最后一是那也是类似的,
在这里插入图片描述

那我们来看看位的函数主要都做了哪些事儿?那在weight函数的一开始呢,在这个循环中,首先它要构造一些事件,对吧?都有哪些事件进行侦听?那么,需要把要侦听的这些事件呢?塞到这个事件数组中。
在这里插入图片描述

之后呢,它会处理所有的socket。从每一个dispatcher中拿到它的socket的描述符。那之后呢,通过event select将这个socket与事件进行一个绑定,对吧?
在这里插入图片描述

之后呢?当有事件发生的时候,我们就可以知道是哪个socket触发的事件。好,如果我们拿到的这个socket,它不是一个真正的socket。那有可能是一个普通事件,对吧?那我们就把它当做一个普通事件,塞到事件处理函数中之后呢?就是调用wait for multiple event这个API。进行事件等待。当有线程触发了事件之后呢,它就会对返回值做一些判断,如果失败了怎么样?
在这里插入图片描述

否则成功了,它会根据返回值计算出发生事件的索引,最终呢,从事件。owner数组中取出对应的dispatcher。那么,拿到第四拍摄之后,进行相应的处理。另外呢,返回的index也是有两层含义。那一种呢,是普通的事件的index,另外一种呢,是socket index,那对于socket来说。
在这里插入图片描述

它会进入到socket处理逻辑中,就会遍历所有的dispatcher,那看看是不是对应的socket触发了事件。

如果是的话,就会进行socket枚举,最终呢,找到是谁触发的事件,从而处理相应的socket,对吧?这就是。这段逻辑,它的一个主要工作。OK,那下面呢?我们就来看一下是谁触发的事件呢?
在这里插入图片描述

你继续执行。在397行的wake up socket server就是触发事件的API。那在它内部呢,会调用socket server的wake up函数,从而呢,将等待线程换解,那下面呢,我们就通过这个调用站来看一下到底是谁?触发的这个事件。这个调用站啊,是从上到下看,也就是说最顶上的是我们最近调用的函数,最底下的呢是它的源就是谁调用的?那首先我们将调用站往下拉动,我们可以看到一个非常熟悉的身影,
在这里插入图片描述

就是create modular peer connection factory这个API。也就显然,这个事件呢,是我们在调用peer connection对象的时候触发的,对吧?在它内部呢,是做了多层的调用,那这些调用呢,我会在后边向你做介绍,那么我们再往上找找。找谁呢?找我们比较熟悉的API在这一块儿,我们会看到。当peer connection factory创建成功之后呢,它会调用initialize来对这个对象进行初始化。

初始化的时候又会创建China manager,那manager创建好之后呢,又会调用它的nit。那我们看到这个标记之后呢?往上找。你就会发现在113行有一个invoke函数。
在这里插入图片描述

那113行的含义就是向网络线程发送一个消息,那这个消息呢?就是由我们括号中的这段代码来组成的。对,也就是说,让网络线程来执行这段代码,因为是在创建peer connection factory对象,所以它一定是在信令线程。所以是信令线程调用了invoke向网络线程设置的一个任务。
在这里插入图片描述

那这个任务是什么呢?就是这个匿名函数。那这个任务就会被插入到网络线程的队列中,那我们继续执行啊。那任务插入成功之后呢,就会触发一个事件,那这个事件呢,就是由wake up socket server来触发的,那在这个函数中呢,又会调用。socket server的wake up函数。在wake up函数中,会调用signal wake up的signal方法。好在,signal方法中呢?
在这里插入图片描述

会调用。wsa set event,那像physical socket server触发一个普通事件这样呢,它又开始执行1857行以后的代码了。
在这里插入图片描述

那以上呢,就是web rtc线程事件的处理逻辑OK,那通过上面的讲解呢,你应该对。y8 rtc的事件处理逻辑非常清楚了,对吧?知道了,等待线程它都做了哪些事情?发送线程又做了哪些事情?那关于我们在代码调试过程中出现的invoke sent post等这一类函数呢?我们在后边的课程中再向你做详细介绍。

那这些呢,涉及到线程的切换,以及像其他线程队列中插入消息等,这一系列操作,那这一些呢,我们都会向你做详细介绍。那我们今天的课呢,就到这里有任何的问题呢,您可以到讨论区或者是群里去给我留言,我在那里呢,给你做详细解答好,谢谢。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/79379.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ArcGIS标注的各种用法和示例

标注是将描述性文本放置在地图中的要素上或要素旁的过程。 本文整理了ArcGIS中的各种标注方法、可能遇到的问题和细节,内容比较杂,想到哪写到哪。 一、正常标注某一字段值的内容 右键点击【属性】,在【标注】选项卡下勾选【标注此图层中的的要素】,在【文本字符串】栏中…

【SpringBoot集成Redis + Session持久化存储到Redis】

目录 SpringBoot集成Redis 1.添加 redis 依赖 2.配置 redis 3.手动操作 redis Session持久化存储到Redis 1.添加依赖 2.修改redis配置 3.存储和读取String类型的代码 4.存储和读取对象类型的代码 5.序列化细节 SpringBoot集成Redis 1.添加 redis 依赖 …

指针进阶(2)

6.函数指针数组 数组是一个存放相同类型数据的存储空间,那我们已经学习了指针数组, 比如: int *arr[10]; //数组的每个元素是int* 那要把函数的地址存到一个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢&…

dart项目规范

​ dart项目结构 假设有一个名称为 enchilada 的完整的包目录(基本用到了所有的子目录),那么它的目录结构看起来像下面这样: enchilada/ .dart_tool/ * .packages * pubspec.yaml pubspec.lock ** LICENSE README.md CHANGELOG…

【LeetCode每日一题】——面试题10.11.峰与谷

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 排序 二【题目难度】 中等 三【题目编号】 面试题10.11.峰与谷 四【题目描述】 在一个整数…

灰度变换原理//test later

灰度变换原理 图像灰度变换变换原理:通过变换函数T将原图像像素灰度值r映射为灰度值s: 2、灰度反转 2.1原理 灰度反转:将图像亮暗对调,可以增强图像中暗色区域细节 ��(�)�−1−…

【C++】哈希表的实现

哈希是什么理解哈希哈希所用的容器计算key值方法哈希的插入和查找解决哈希冲突闭散列也叫开放寻址法开散列 哈希闭散列实现闭散列结构闭散列结构插入闭散列查找闭散列删除 哈希开散列实现(链表式)开散列结构开散列结构插入开散列结构查找开散列结构删除 …

Map和Set及其实现类详解

目录 一, 搜索 1,传统搜索 2,Map和Set模型 二, Map的使用 1,Map接口的继承及实现图 2,Map接口的使用 3,TreeMap和HashMap的使用和对比 1,TreeMap 代码示例 map中插入的数据按照key进行排序 map中插入的数据必须具有可比较性(或者实现了比较器相关接口) ​map中插入…

Echarts 折线图的详细配置过程

文章目录 折线图 简介配置步骤简易示例 折线图 简介 Echarts是一款基于JavaScript的开源可视化库,由百度开发和维护。它提供了丰富多样的图表类型,其中折线图是其中一种常用的图表类型。 折线图通过连接数据点所形成的折线来展示数据的变化趋势。在折线…

互联网3.0 数字原生——数物虚实多维细粒度泛在融合

随着计算机、宽带网、通信技术的飞速发展,互联网技术和软硬件系统也不断演进,催生了一场前所未有的数字化革命。从Web1.0到Web3.0,以及虚拟现实、人工智能和数字孪生等领域的崛起,每一步都勾画出了一个崭新的数字未来,…

实战SpringMVC之CRUD

目录 一、前期准备 1.1 编写页面跳转控制类 二、实现CRUD 2.1 相关依赖 2.2 配置文件 2.3 逆向生成 2.4 后台代码完善 2.4.1 编写切面类 2.4.2 编写工具类 2.4.3 编写biz层 2.4.4 配置mapper.xml 2.4.5 编写相应接口类(MusicMapper) 2.4.6 处…

高效成绩查询系统助力,让学校管理事半功倍

各位老师们,大家好!作为教育工作者,我们都了解成绩查询在学校管理中的重要性。然而,传统的查询方式往往繁琐耗时,给我们带来了不少困扰。因此,今天我将向大家介绍一个极其便捷的查询工具,能够帮…

生成式人工智能在高等教育 IT 中的作用

作者:Jared Pane 通过将你大学的数据与公共 LLMs 和 Elasticsearch 安全集成来找到你需要的答案。 根据 2023 年 4 月 EDUCAUSE 的一项调查,83% 的受访者表示,生成式人工智能将在未来三到五年内深刻改变高等教育。 学术界很快就询问和想象生…

盘点:人工智能发展趋势下的4大常见AI算法以及应用场景

近年来,人工智能的发展速度十分惊人,在安防监控、工业制造、农业、教育、金融、医疗等领域中的应用越来越广泛,并且未来几年也将继续保持高速的发展趋势。通过人工智能技术提高自动化程度、减少人工干预、提高监管效率,已经成为当…

虚拟机Ubuntu操作系统常用终端命令(2)(详细解释+详细演示)

本篇概要 本篇讲述了Ubuntu操作系统常用的几个功能,即超级用户,虚拟机系统损坏如何修复,用户和组,如何以root登录界面以及文件的权限方面的知识。希望能够得到大家的支持。 文章目录 本篇概要1.超级用户1.1使用超级用户1.2切换到…

【Robotframework+python】实现http接口自动化测试

前言 下周即将展开一个http接口测试的需求,刚刚完成的java类接口测试工作中,由于之前犯懒,没有提前搭建好自动化回归测试框架,以至于后期rd每修改一个bug,经常导致之前没有问题的case又产生了bug,所以需要…

Feign远程接口调用

概述 目的:解决微服务调用问题。如何从微服务A调用微服务B提供的接口。 特性: 声明式语法,简化接口调用代码开发。像调用本地方法一样调用其他微服务中的接口。集成了Eureka服务发现,可以从注册中心中发现微服务。集成了Spring…

一文详解TCP三次握手四次挥手

文章目录 TCP的三次握手和四次挥手三次握手四次挥手 TCP的三次握手和四次挥手 基本概念 SYN(Synchronize Sequence Numbers,同步序列数字):用于建立连接的同步信号。 SYN 序列号的作用是用于标识每个数据包中的字节流的起始位置。…

Java基础入门·File类的使用

前言 ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ File类的创建方法 File类介绍 ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ …

docker 数据持久化

文章目录 定制镜像持久化需求实现 数据卷持久化数据卷简介数据卷的特性创建读写数据卷停止容器后的操作查看数据卷详情 创建只写数据卷查看数据卷详情 创建共享数据卷 Dockerfile持久化创建Dockerfile、构建和运行镜像查看宿主机端的目录 在容器层的 UnionFS(联合文…