00:00
好,大家好,我是林声教育的mark克老师,这节课呢,Mark克老师跟大家一起来聊一下SCCH的网络模块的封装啊,我相信呢,大家在工作当中呢,呃,肯定会有碰到我们的项目当中会有一些网络模块封装的一些问题,对不对,不知道如何从从哪些地方入手,或者是我们不知道这个网络模块该怎么去分析,那么马克老师呢,这节课从这三个角度来帮助大家来了解一下,在于我们的scan对于一个阿并发模型,它是如何来做这个网络模块封装的,好那么这三个角度呢,分别是首先我们来了解一下react网络模块的封装,它有哪几个分析的要素,第二个呢,就是我们scan是属于一个阿的并发模型,那么我们的这个网络数据,它是如何被传传递到我们的after当中去的?好,第三个角度呢,就是跟大家来讲解一下我们的scanner,它是如何在我编程的过程当中实现这一个同步非阻塞的操作。
01:01
好,大家现在对这个概念不清楚的朋友,没有关系,那么等一下mark克老师呢,会跟大家进行详细的介绍,好,那么呢,首先允许马克老师呢跟大家来介绍一下scan。好,什么是scan呢?啊,我们用一句话来跟大家来进行总结,就是它是用一个用C。加上Lu啊实现的,呃,一个我们的阿啊并发。啊,并发编程模型啊,那么这句话如何来理解呢?C和Lu是告诉大家,就是我们呢,主要是用C语言和lur来进行实现的,好,那么我们的阿的并发编程模型是怎样的一种编程模型呢?好,如果大家有了解过along的朋友呢,应该会知道他是从呢西语啊,从我们的语言层面来实现的。好语言层面实现的阿并发编程模型。
02:04
好,那么什么是阿并发模型呢?那老师用一句话来跟大家总结,阿,就是抽象的进程。什么叫抽象的进程呢?我们进行编程的时候,通常都是我们所说的内核进程,内核进程当中呢,我们再往下面,呃,进行一个细的调度,就是我们的线程了,对不对?好,这个时候呢,我们的阿的并发模型呢,它是在用户层去抽象一个进程,好一个并发的实体。好,那么大家可以看到这张图啊,等一下马克老师看一下我们的这个截图,为什么。哦,还有一个稍微等一下麦克老师把这个。啊,这个打开稍微等一下,好,那么我们阿的抽象的进程是什么样子的概念呢?大家可以看到这张图啊,这张图呢,就跟大家描述了一个阿的一个并发编程的模型,好我们呢,具体业务逻辑的运行会在我们用户抽象的这一个进程当中呢进行执行,好大家注意了,我们此时呢,会在一个进程当中,一个内核进程当中会开启多个我们的用户抽象的进程,那么我们这些进程之间是如何来进行通讯的呢?好,就是我们自己抽象的这些进程,好它是通过消息的方式来进行沟通的,大家可以看到麦克老师画的这一个箭头就是我们after,如果要进行交互的话,我们是以发送消息的方式来进行,好,那么我们的这个消息,它总会有一个先后到达的次序,对不对,那么我们呢,会用一个队列来存储我们,呃,发送过来的消息对不对?好,发送过来的消息好,那么麦克老师呢,来跟大家来进行一。
03:51
一个抽象,抽象就是我们的阿的组成部分。好,首先呢,第一个我们需要知道阿呢,它本身需要有一个提供一个隔离的环境,对不对,它既然是一个抽象的进程,那么我们的这些进程,它的运行环境应该要相互隔离,对不对?好,它首先需要有一个隔离的运行环境,好这是那么在我们的scan当中呢,它是采用nova虚拟机的方式来实现的,我们用一个多个nova虚拟机相互隔离它们之间的运行环境啊,那么刚刚玛克老师也跟大家介绍了,就是我们的act之间,他们之间的通讯交互,我们呢是通过消息的方式来进行进行。
04:37
而交互的对不对,好,那么我们这些消息呢,又需要有一个载体来进行。组织对不对,那么呢,我们会这里呢,会有一个消息队列。消息队列呢,它主要的作用当然呢,是存储我们啊,先后到达的我们的消息对不对。好,第三个呢,就是我们总要有一个来运行我们的这个act的一个依据,对不对,好怎么来运行我们的act呢?好,那么我们主要采用一个,我们需要给它设置一个回调函数,这个回调函数的主要的作用呢,就是用来执行我们的这个阿,好,它的作用是用来执行我们的。
05:22
这个呢,就是我们一个act,它应该要构成的几个关键的因素,对不对啊,那么我们呢,也把这里面的关键的关键字给它抽象出来,第一个呢,是我们的act啊,就是我们的scant呢,也可以用这三个关键字来描述我们的scan,第一个就是阿隔离的环境抽象的进程,好第二个呢,就是我们是消息,我们所有驱动阿运行的都是来源于消息。好,第三个关键字呢,就是携程,好,我们为什么需要携程呢?好,大家可以看到我们的这个回调函数用来驱动我们的阿,那么也就是说我们这个阿的运行当中可能会涉及到多个回调,里面可能会有很多很多的回调,对不对?如果逻辑相关的话,我们就会陷入JS,不知道大家有没有开发过我们的javascript,就是note JS,不知道大家有没有开发过note JS呢?它这里面就会有一个啊回调陷阱对不对。
06:25
所谓回调陷阱呢,就是我们里面会有很多的嵌套回调好,那么我们scanner呢,为了解决这一个千套回调的陷阱,那么呢,我们给他。加入了我们lur当中的一个携程好,尽量呢避免我们的回调对不对,好这个呢,就是我们scanner的三个关键特性,After消息好,携程好,那克老师呢,再跟大家来介绍一下我们的这一个消息,Scanner当中的消息分为哪几种,哪几个类型呢?啊消息的类型,消息的类型呢,主要是来驱动我们大家可以思考一下,我们作为一个进程,作为我们开发的一个服务器,有哪些因素,它能够驱动我们服务器的业务的进展啊我们的这个服务器,它的这个进程,它是如何来驱动它进展的,对不对,有哪几种类型呢?大家可以想象一下,首先我们首先要处理的就是一个网络消息对不对,我们客户端给我们发送消息,比如说我们与嗯数据库建立连接,数据库要给我们回消息,那这些消息呢,都能够驱动我们服务器的业务逻辑的进展,对不对?
07:37
好,这是第一个,第二个呢,我们需要考虑的是一个我们定时消息对不对,好在我们scan当中还有一种消息,其实刚刚麦克老师已经跟大家说了,就是我们的阿之间他们有一个交互对不对,那么这个交互的消息呢,就是我们阿之间的消息对不对,他也能够驱动我们业务逻辑的进展啊,就是我们两个阿之间相互交换数据,那么呢,这样也会。
08:05
也能够驱动我们具体的业务逻辑的进展,对不对?好阿之间的消息,好,那么呢,在到达这里,马克老师呢,几乎把我们的scantch能够描述scantch的内容呢,都把它体现在这里了,好,Mark克老师再来跟大家进行回顾一下,什么是SCSC呢?它是用lua跟C来从框架层面,大家注意了,它是从框架层面,它不是原生的阿尔的并发模型,像along,它从语言底层就已经实现我们的阿并发模型,就像构言,它从底层就实现CSP并发模型,对不对,它是用构语言从语言层面去实现我们的CSP并发模型,啊,我们这里呢,是从框架层面去实现阿并发模型,那么阿并发编程模型有哪些重要的点呢?好,那什么是阿呢?好,阿是一个抽象的进程,就是我们在用户好,在用户层去抽。
09:05
抽象多个进程好,抽象多个进程好,那么我们的这个阿的组成部分是什么呢?就是我们的阿它有哪几个核心要素呢?第一个我们既然抽象进程,就首先考虑的是我们进程之间的一个隔离的环境,我们期望我们进程之间的运行不会被其他进程的运行呢所干扰,对不对?好,那么呢,我们用一个lur虚拟机去实现这一个隔离的运行环境,那么我们阿之间又是怎么,我们的阿它是怎么运行的?运行的依据是什么呢?好,它是通过消息来驱动我们的阿运行的,那么这个消息存储在哪里呢?它存储在我们的一个消息队列,为什么我们需要消息队列呢?因为我们的这一个after的运行,它可能有多个,多个嗯,多个实体来驱动它,那么我们总会有一个消息的先后顺序,对不对?那么我们就需要有一个这样的数据结构来组织我们的这个消息,好,那么具体是怎么来运行的呢?那当然是通过一个。
10:05
回调函数,那么回调函数呢,就是把消息作为参数,把我们的消息作为这个回调函数的参数的方式来驱动我们阿的运行,好那么我们能不能用极极少的关键字来总结我们的SC呢?来描述我们的SC呢?好,那么它主要有三个特性,第一个after,好,就是抽象的进程,第二个就是我们消息,我们是通过消息来进行交互的,来驱动我们业务逻辑的,好那么我们为了不进入。不陷入这一个回调陷阱,那么呢,我们需要引入携程去粘合这些回调,好那么麦克老师这些呢,都会跟大家来介绍这节课。好,那么我们也需要知道这个消息它有哪些类型好网络消息,定时消息以及阿之间的消息,好那么我们今天需要解决的问题是什么呢?我们解决的问题是这个网络消息他跟我们的@是什么关系,是怎么来驱动我们的这个流程的?好那么麦克老师来跟大家介绍一下,首先我们的SC呢,它会进行一个网络模块的封装,对不对?好,这样呢,我们才会来产生这个网络消息对不对?好,我们从这一个网络消息的产生出发,首先呢,我们SKY的网络模块。
11:25
好,那么这个网络模块呢,它是好,它是我们的一个react网络模型,好我相信呢,大家可能如果从事我们的后端开发有一段时间的朋友呢,应该听说过我们的react网络模型,那么同样的,按照mark克老师刚刚分析问题的思路,同样如此,我们来介绍一下react网络模型,那么首先我们也从组成部分出发啊,组成部分出发,我们的react网络模型它有哪些部分构成呢?好,第一个它是有我们的IO多的费用,好,再加上呢,我们的非阻塞L。
12:08
好,那么这个组成部分呢,并不能够来帮助我们来分析我们的这个网络模型,因为呢,它比较太宽泛了,我们能不能够用更加直白的词汇来形容我们的这个组成部分呢?好,那么麦克老师跟大家介绍一下,首先我们需要知道IO多的复用,它主要的职责是什么?好,麦克老师跟大家介绍一下,它主要的职责是做的IO检测,好,那么从封装层面刚刚是从组成部分出发,好,那么我们从封装层面出发,那么我们应该怎么去封装react网络模型呢?好,麦克老师跟大家介绍一下。好,同样的呢,IO多路复用它主要的职责好,它主要的职责是做我们IO检测的,我们需要从IO检测首先要封装好,那么这些非阻塞O呢,主要是指的我们具体的IO操作,那么这个IO操作包括哪些呢?比如说我们connect对不对,好,去连接第三方服务,还有呢,我们accept接收客户端的连接对不对,好,比如说还有我们read从网络当中读取数据,还有呢,我们write把数据发送到对端去,对不对,好,把数据发送到对端去,这些呢都是指IO操作,那么我们从封装的层面而言呢,我们也要去封装它的构成部分,对不对,好,那么我们还需要封装我们的IO操作好,那么IO检测它又有哪些可以,能不能够细分呢?因为这一个还是比较。
13:44
啊,比较那个太宽泛了,对不对,大家还是还是不能够get到他的点,那么麦克老师来跟大家来说一下,从封装层面的IO检测出发呢,我们首先需要去封装一个。啊,事件操事件控制。
14:01
好,第二个呢,就是我们的事件循环。就是从IO检测封装层面而言,我们要做两件事情,第一个去做事件控制,事件控制是什么意思呢?就是我们去注册事件,注册事件,或者是呢,把这个事件注销,或者是我们去修改这个事件,呃,事件类型啊,那么呢,这些都是属于事件控制,那么我们通常如果我们在另一个项,那么我们通常呢,采用的control。好,通过e controltl这个接口来做我们的事件控制好,那么我们的事件循环是什么意思呢?事件循环是我们通过一个阻塞的调用,从网络当中收集出所有被触发的事件,把它弄到我们的用户态来啊,把到我们的用户态来,我们把这些事件都收集好,那么呢,我们用一个数组接收,接收之后我们再用一个for循环,把这些事件呢进行便利处理,这个能听明白的朋友帮刷。那么如果我们用linuxcel的E呢?那么我们通常要去封装e weight好,E wait它呢来封装一个事件循环,好,这个是从IO检测的出发,我们需要封装这两个点,好,那么我们的IO操作呢,要封装哪些点?
15:22
好,IO操作我们需要封装哪些点好,那么我们呢,主要从这个IO操作的职责出发,什么叫职责?就是我们要处理哪些事情出发,麦克老师来跟大家来说一下要封装哪几个层面,第一个层面我们首先需要处理的是连接的建立。连接的建立呢,主要要处理哪些东西呢?好,那么在这里面分为两个,第一个呢,是我们作为客户,作为服务器处理。处理客户端的连接啊,处理客户端的连接,那么我们服务器呢,也有可能作为客户端去连接第三方服务,对不对,比如说我们要连接red,连接MY对不对?好,还有呢,处理作为客户端就是处理中间键的连接对不对?好,第三方连接我们把它称之为第三方连接,第三方连接就是我们的服务器作为客户端。
16:19
好,我们在这里写一下。啊,作为客户端去连接我们啊,比如说我们的这个是服务器,这个呢是red my,那么我们还需要跟他们建立连接,对不对?当然呢,我们也要处理来自客户端的连接,客户端也要跟我们的服务器建立连接,好我们主要呢要处理这两块的内容,这个是连接的建立,那么第二个层面呢,作为通常我们的连接的建立,通常是一个对象的产生,对不对?比如说我们一个用户啊,用户跟我们的服务器建立连接了,那么接下来我们就需要去创建初始化我们的用户了,对不对?那么呢,这个就相当于我们的用户的创建,接下来的流程就是我们用户的创建,那么作为一个用户对象的生命周期,既然有连接的建立,那么既自然就有连接的断开,对不对啊,连接的断开。
17:10
好,那么连接的断开呢,我们也要分几个层面,为什么呢?第一个我们要主动断开对不对?好,我们服务器内部可能由由于某种原因,就是觉得你操作不当,那么呢,我们要把这个连接主动断开,对不对,好,这是主动断开。那么还有一个呢,就是我们的被动断开啊,被动断开连接,那么被动断开连接显然呢,我们需要来接收这个IO检测,检测到这一个客户端断开连接的消息过来了,那么接下来呢,触发我们相对应的被动断开连接的业务,对不对?好那么麦克老师呢,等一下也会跟大家进行详细的讲解,好连接的建立跟连接的断开直接触发了我们的一个对象的生命周期,对不对,好,那么。连接建立跟断开之后呢,我们还要接收来自客户端的一些数据,对不对,好数据的到达,好数据的到达,数据的到达呢,我们通常也要分为。
18:11
在我们的网络封装层面而言,我们也要做两个方向的封装。好,也要做两个方向的封装,哪两个方向呢?第一个我们要读取固定字节的,好读取固定字节。数据好,第二个封装呢,我们需要封装读取。特殊字读取。啊,特殊字符风格的。啊。好,那么在这里面呢,我们也要从两个方向来进行封装,第一个呢,我们通过read,我们要去封装一个接口,一个read read什么呢?Read的多少个size,通过这个FD,我们这一次呢,一定要读多少个长度的数据啊,这个长度呢就是size子,为什么我们要做这两个层次的封装呢?好,因为我们。
19:07
我们要考虑的是界定一个数据包,因为数据到达我们服务器的时候,我们首先要解决的问题就是要界定数据包对不对,好,界定数据包呢,就也分为两种,对不对?界定数据包那么呢,我们要么就是以固定长度的,我们会有一个头,头会告诉我们后面要接收多长多长的数据,比如说有1000个字节,那么呢,首先的这个头告诉我们要读1000个字节,那么接下来呢,我们就读1000个字节,对不对,好,这是一种界定数据包的方式,那么还有一种界定数据包的方式,比如说像我们的TEL net TEL net以杠N进行分割我们的数据包对不对,那么呢,我们也会去读那个特殊字符,读这个分割符对不对,比如说以杠N,好,那么我们呢,需要读这么多数据,好,那么这个呢,就是我们的数据到达,那么在于我们的网络层封装而言,我们要封装两个接口,第一个读取固定字节的数据,第二个呢,读取分割符,分割的字符数据,对不对?
20:04
好,这个呢就是数据的到达,那么还有一个呢,就是数据的发送,好数据的发送完毕,那么数据发送完毕呢,我们需要考虑的一个点是什么呢?对于我们的网络编程而言,对于我们的网络模块编程而言,我们的数据发送完毕不是指我们的这个数据发到客户端,比如说这个是我们的服务器,不是指我们的数据发送到客户端,是指我们的数据呢发送到我们的内核协议站对应的我们的某一个FD所对应的写款中去,我们只是把数据写到这个写款中去,对于我们的网络编程而言,我们的任务就已经完成了,至于这个数据是不是到达了我们的这个客户端,我们的网络编程它是没法处理的,好,这个呢,是需要需要大家关注的一个点就可以了,好,那么麦克老师来跟大家来进行回顾一下。对于我们的react网络编程模型而言,那么呢,我们需要考虑的几个点,从封装层面,第一个我们需要封装一个IO检测,IO检测的职责呢,主要是。
21:10
分为两个块,第一块呢,我们需要来做事件控制,事件控制呢就是我们要去注册事件,注销事件以及修改事件,好第二个层面呢,我们需要考虑一个事件循环,也就是用阻塞接口好从网络当中把我们最近触发的这些事件,把它从内核当中拷贝到我们的用户带来,接下来我们会有一个循环。依次去处理从网络当中触发的消息啊,触发的事件啊,那么这些事件呢,相对应的这些事件循环当中就会包含我们具体的IO操作,那么IO操作呢,那么接下来就是我们的IO操作,IO操作呢,我们要注意我们需要处理四个点,第一个连接的建立啊,也就是对应的这个接口呢,麦克老师也写下了连接的建立,比如说我们的connect。
22:01
好,这个呢是我们处理第三方服务,就是我们服务器作为客户端的时候的啊IO操作,那么这个呢,就是我们需要调用service接口接收客户端的连接,好主动断开,那么显然我们通常用到的是close,对不对,Close fd,好被动断开,那么在这里面等一下马克老师会跟大家来介绍一个概念,也就是我们的半关闭状态。好,连接的半关闭状态,好,等一下麦克老师再跟大家介绍,那么我们还有一个呢,就是数据的到达,数据的到达呢,我们通常要封装两个接口,第一个读固定字节的数量,对不对,Read n好,那么还有一个呢,就是read。啊,Read line,我们通常把它称之为read line,那么从网络封装而言,我们需要分封装这两个层次。好,那么还有一个呢,就是数据的发送完毕,那么通常对应的我们的IO操作的接口就是对不对,或者是我们send对不对,好,这个read呢,就可以大家把把它理解为receive对不对都可以,这两个接口呢都是可以的。
23:10
好,那么我们这样子是不是就已经完成了呢?好,显然呢,对于封装层面而言,我们还缺了一个重要的载体,什么叫重要的载体呢?好,我们还缺乏一个事件对象的封装,也就是说,从封装层面而言,我们应该由三个部分构成,哪三个部分构成呢?第一个IO检测,第二个IO操作,还有一个呢,事件对象的封装。好,那么我们对于react网络编程。我们呢,应该要封装这三个层次。好,那么我们能不能够用像scanner一样,用几个关键字来描述我们的react网络模型呢?我们刚刚的用这三个关键字对不对?那么我们react网络模型它的关键字呢,只有两个,第一个一步,第二个事件啊,它是以事件驱动的方式啊,它事件到达之后,我们是通过回调函数的方式呢,来处理我们的这个,呃,网络事件,这个能听明白的朋友帮马克刷,就是我们的react网络模型,如果用两个关键字来形容它的话,那么呢,就是异步事件,好异步呢是主要是指我们的这一个行为,就是事件到达之后,我们是怎么处理它的,通常呢,我们是以回调,它会割裂我们的业务逻辑,好那么这个事件呢,主要是指我们会将这种对IO的操作,把它转化为对事件的处理好,那么我们呢,会在这里面进行一层包装。
24:41
好,这个就是事件,好,那么我们呢,把这两个关键字呢,都把它封装,呃,都放在这里。那么接下来我们就看这几个关键字之间怎么起化学作用了,对不对?好,我们把那个写一下SC的关键字act。好,还有一个关键字呢,就是我们的消息好,以及携程这个是我们SC的关键字,那么我们的react的关键字呢,就是异步啊,还有呢,就是事件。
25:13
好,那么我们现在要处理的问题是我们在SC当中去封装这个react网络库,显然我们需要处理这五个关键字之间的关系,对不对?好,那么麦克老师来跟大家简单的先梳理一下他是怎么来处理的。首先事件。我们需要把它包装成消息,因为我们的阿的并发模型的,呃,运行实体,它是我们的这个消息啊,不是不是运行实体,运行实体是我们的阿,消息是驱动我们阿的,呃,关键数据对不对,那么我们需要把这个网络事件包装成消息,这个能听明白的朋友帮麦克老师阿姨,第一个呢,我们事件。需要包装成消息。好,这是第一个,第二个点,我们需要来了解。
26:04
这个事件就是我们的这个消息,它是怎么,就是我们的这个具体的网络消息,网络事件,因为它会包成人消息,对不对,那么这个网络事件它是怎么去传到。具体的某一个阿的啊,不知道大家能不能理解,因为呢,在我们的SC当中,它会有成千上万个阿,那么现在网络事件到达了,网络事件到达了,它到底是传给哪一个阿呢?好好,我们的事件是怎么传到阿当中去的?好,那么大家可以思考一下,比如说我们某一个消息,某一个当中我们处理了网络消息对不对?好,我们在这里面设置了一个处理网络的接口,那么我们怎么来确保这一个以后的。这个相关的FD的网络事件都能够传递到这一个,对不对?好,那么实际上要处理的问题是什么呢?就是我们的这个网络消息,网络事件怎么跟act进行绑定。
27:07
好,这里肯定是需要绑定的,对不对,那么我们需要来了解它是怎么绑定的,对不对,好。第三个我们需要了解的是。我们的这一个携程啊,因为刚刚麦克老师第三个点,其实麦克老师也跟大家描述了,对不对,网络操作当中的同步非阻塞,大家看到这个同步的字,我们的react,它是一种异步的,好那么我们怎么把这个异步转化为同步呢?好那么就是我们第三个需要解决的问题。啊,就是携程是如何。好,如何将异步的操作转换为同步。
28:01
好,这个能听明白的朋友帮马克老师,接下来呢,马克老师就一个一个来跟大家来解决这些问题,好这个上面的这几个关键字,有疑问的朋友呢,现在可以说出来,那么马克老师呢,可以跟大家来解释一下,大家能听明白的朋友巴,马克老师阿姨好,这三个是我们的scan的关键字,这里呢是我们的react常见的react网络模模型,它的关键字两个关键字,好那么迈克老师再把这一个呃思路跟大家捋一下,我们呢需要将这个事件,因为这个是我们实际要运行抽象的实体,对不对,我们要抽象成这个样子,现在呢,我们引入了一个react的网络模型,那么呢,接下来我们就需要首先把要把这个事件把它抽象成这个消息,对不对,应该也叫转换成消息,对不对,把这个事件包装成我们具体的消息,那么第二个呢,就是我们的react网络模模型当中有一个重要的特性,就是它是一种异步特性,对不对?好,那么我们呢,会通过携程的方式,将这个异步的方式呢,转化为同步的操作,好转化为同步的操。
29:02
操作,那么还有一个就是我们的消息,它是怎么就是网络消息,因为我们今天主要的讲解的目标就是我们的网络消息。跟我们的阿框架的融合对不对,那么我们势必要解决一个问题,就是我们的这个网络事件怎么跟阿进行绑定好,这个能听明白的朋友帮老师阿姨,那么接下来呢,我们就把这一层关系呢给捋清楚。好,那么接着首先我们来看一下这个网络消息,就是网络事件怎么转化为消息,好,那么老师呢,带领大家看一下源码。好,这个呢,是麦克老师下载的SCTCH的源码,大家可以看到这是SCTCH源码,那么我们怎么去找我们今天的这个。这些问题呢,好,首先我们从这一个,呃,因为它是一个react的封装,对不对,那么迈克老师呢,首先带领大家看一下我们的网络线程是怎么来处理我们的网络事件的啊,大家看到这个呢,是。
30:02
网络线程,网络线程,那么接下来呢,这里有一个for循环,For循环好,那么大家可以看出来,这个地方肯定封装的是事件循环。好,这个能听明白的朋友帮老师刷一,这个呢就是我们的事件循环,事件循环呢就是我们网络封装的时候。好,迈克老师把这个。截一下。好,那么麦克老师呢,带领大家看一下,这个呢,就是我们的网络事件循环,网络事件循环主要的职责是什么?好,主要的职责是从我们的内核当中,把这些就绪的事件,把它拷贝到我们的用户态来,那么用户态呢,就会有一个或循环,或循环呢,把这里面的事件呢,一个一个的进行处理好,一个一个的进行处理好,那么也就是我们这里面主要做的事情,好那么我们来看一下怎么来进行封装的呢?啊,我们带领大家来看一下。好,那么我们走到这一个socket,那么接下来呢,就会到sockage serve,那么显然还会有下一层封装,对不对?那么我们来看一下下一层封装好socket server po,那么大家需要注意的是,我们现在呢,会把这个啊,Socket message这里呢是我们的网络消息,那么这个网络呢,这个相当于我们的网络事件,好那么我们在显然在这里面呢,会去填充这个网络事件,对不对?好,填充网络事件我们来看一下它的网络填充事件是如何来做的,好首先呢,我们进入到这里。
31:36
进入到我们的这个函数啊,这个是我们的网络视线循环当中所需要处理的内容,那么大家可以看到我们的很快就可以走到这个SP。SP就是我们的事件循环的关键一步,就是对我们的一位的封装好,等一下我们把这个呢稍微设置一下。好,那么我们来看一下这一个流程,一。
32:04
好,我们把它点进去。好,看到这个的朋友帮马克老师刷一,这个是我们的一。好,这个呢,显然是对于我们的事件循环的封装,对不对,就是从网络当中取出我们所有的事件,那么这个呢,我们会用这一个数组接收所有被触发的事件,好,拿到这些事件之后呢,我们就需要来进行啊,进行后面依次来处理所有的消息,对不对,好,我们都会全部填充到这一个一的结构当中啊,填充到一的结构当中。好,填充到一的这个结构当中,1V当中,好,那么接下来呢,我们就会依次去取,从网络当中去取这一个消息,对不对,从我们的视线循环当中依次的去取出消息。好,那么麦克老师呢,先来跟大家把这几个关键要素跟大家整理一遍,这几个关键要素跟大家整理一遍,首先我们来看一下事件控制在哪里,事件循环呢,我们已经知道了,就是在这个SP当中呢,去做的我们的事件循环的封装对不对?那么事件控制的循环,呃,事件控制的封装在哪里呢?好,显然呢,它会在e control当中对不对。
33:14
好,那么我们来看一下e control的封装。好,大家看到e control的朋友帮马克刷好,这里呢有三个都是e control对不对?好麦克老师一个跟依次跟大家来进行介绍,E呃,Spr的就是我们的事件控制当中的注册事件好,它是注册事件事件控制当中好,还有一个呢,就是删除事件,就是去注销我们的事件好,SPD好,还有一个呢,就是去enable。Enable我们具体的事件就是去修改我们的事件,是把我们的读事件开关闭,还是把我们的读事件开启,或者是把我们的写事件关闭,或者是把我们的写示件啊开启好,那么这个呢,就是我们的SP,那么我们的事件控制呢,主要由这三个接口来控制的好spr的SPD以及我们的SP好,那么接下来我们接下来再看这些IO操作的封装。
34:12
IO操作的封装呢,麦克老师跟大家介绍一下,我们会把所有的网络世界呢,再进一步抽象啊,大家看到这个呢,是啊,我们从网络当中取出来的具体的一个触发的事件,取出具发具体的事件之后呢,那么我们会把它们来进行一个处理,大家看到好,可能呢,是我们建立第三方连接啊,我们从上一层给大家看。好,大家看到这个呢,就是从网络当中处理完之后的结果,就是这个tab。好,就是一个事件循环当中,它有很多的事件,我们把这个事件一个一个的处理之后,它会得出处理这个事件的结果。好我们看一下它是怎么来进行抽象的,那么我们主要看这一个type的类型就知道了,好我们把这个呢截个图来帮助大家来理解。
35:07
好,我们来看一下它的一一映射关系是什么?好。好,麦克老师把这个图截完整一点,让等一下呢,大家需要这份文档的朋友呢,可以加下我们的秋香老师啊,我们呢把这个思路呢给大家整理一下,这里呢是我们的事件循环。啊,事件循环处理。那么显然呢,它是一个一个事件的处理,对不对,好,那么第二步呢,就是会把这些这个type这个。这个type呢,就是把我们的事件呢,最后包成包成我们的消息类型,对不对,好,它的返回值是我们具体的消息类型,那么呢,第二个就是我们的。将事件转化为。好,我们来看一下这个事件跟消息类型的转换,好显然呢,刚刚麦克老师跟大家说了,事件到达之后,事件循环做完之后,接下来就是IO操作,对不对?好我们把这三个呢,四个呢把它截一下。
36:13
好,那么我们来找一下他们的映射关系,好,麦克老师一个一个跟大家来映射。首先我们的这个socket data,它其实就是我们这里面的。啊,数据的到达,好,我们呢用红色的。好,这个封装的呢,是我们的数据的到达,好那么还有一个呢,Socket close,显然呢,这一个是我们连接的断开,对不对,好,这个是我们连接的断开。好,那么还有一个socket open soet open是什么意思呢?好,麦克老师跟大家介绍一下,我们作为服务器的时候,那么呢,有客户端,有我们的第三方服务对不对,比如说这个是我们的。好,这个呢是我们的serve好,这个呢是我们的第三方服务,比如说MY好,比如说是MY好,那么现在呢,这个open是指的我们的S与MYSQL建立连接成功的标的消息好,连接建立成功的标记,这个呢就是我们连接建立成功的标记,那么也就是刚刚麦克老师跟他说了,我们的连接建立分为两种,对不对,作为客户端的,那么也就是这个connect好。
37:24
处理客户端的连接,还有一个处理客户端的连接,对不对,那么这个open主要是指这一块好。这个open是指这一块,我们把这个图呢。啊,它是指这一个流程。好,那么还有一个呢,第三个是accept accept呢是指我们接收客户端的连接,当我们客户端跟服务器建立连接的时候,那么呢,我们在这里面会接收到这样的一个消息。好,接收到这样的一个消息,我们的呢,是指这个流程啊,我们用绿色的。好,这个呢,是我们的accept的流程。
38:01
好,那么什么是error呢?好,大家先不用关注这个error error呢是指我们服务器的内部错误,好,我们这里呢,先不用关注,那么我们来看一下exist的也不需要关注,是我们调用close之后,它会设置成这个状态就是。好,那么udp呢,我们也不需要关注,我们来关注一下这个warning warning是什么意思呢?好,麦克老师要要跟大家来详细的介绍网络编程的这个窝消息是什么意思。好,这个呢,Warning其实呢,就是我们的网络异常。好,网络异常呢,在我们的网络编程当中呢,有两种处理方式,有两种处理方式,第一个呢,我们可以用艾欧多的复用来处理。就是我们具体的某一个连接出现异常的时候,那么我们呢,第一个可以通过IO多路复用来进行检测。
39:05
好,那么它具体是怎么来通知我们的呢?我们通常是通过EE的方式,好,通过EE这样的一个消息来告诉我们,好,我们某一个FD出现网络异常了,好,那么还有一种呢,第二种是我们IO操作当中,好IO操作告诉我们。好IO操作的检测,它是怎么来检测呢?就是我们具体的IO操作,比如说我们的read的好,如果它等于负一,它的返回值是等于负一,并且它的这个时候呢,它就会以错误码的方式来告诉我们的这一个具体的FD连接的异常的具体的信息,好那么现在呢,我们的scanner呢,把这一套好用这一个warning的方式呢,来通知我们,好那么我们的Ning消息到达,说明是我们的连接异常了啊,我这里呢,不能说网络异常,最好是说连接异常。
40:04
啊,因为它是指具体的某一个连接。好,这个能听明白的朋友帮麦克老师刷一,就是我们进行网络编程的时候怎么检测连接异常,我们有两种检测方式,第一个我们可以通过IO多路复用来进行检测,第二个我们可以通过具体的IO操作来进行检测,就是我们尝试进行IO操作,那么进行IO操作的时候呢?啊,如果出现连接异常,它会通过具体的返回值等于负一来告诉我们此时出现异常了,那么具体的异常是什么呢?当然是通过这个具体的错误码来告诉我们。这个能听明白的朋友帮麦克老师阿姨,那么这个warning主要是指这一块,我们的连接异常,它也会通过一个消息的方式来通知我们,大家注意了,我们是通过上面的。通过上面的事件操作,将事件转化为我们消息,好,这里呢是描述了我们的消息类型。
41:03
好,这个能听明白的朋友呢,可以帮麦克老师刷阿一,那么接下来我们现在是不是解决了第一个问题,事件是怎么包装成消息的,对不对?那么这个事件包装成消息呢?我们可能还需要进进一步的了解到,为什么呢?因为我们此时只知道这一个消息类型,它到底是怎么转化为我们的scan消息的呢?好,麦克老师进一步带领大家看一下这个代码,好,大家看到这个result呢,在我们的socket从事件处理当中呢,会去包装这一个网络的消事件,对不对?好,然后呢,我们会在这个forward message当中将络的事件包含包装成我们的消息,好,那么在这里面我们来看一下怎么来包装。好这个接口呢,结构体呢,就是描述的scannerch的当中的消息,好anch当中的消息,那么大家可以看出来,它主要通过的是我们的这一个啊,通过的我们这一个。
42:01
事件来填充的我们的这一个消息,好,这个能看明白的朋友帮巴克老师刷一好这个data塔,Data就是这个SSM,它呢就是我们的事件,把这个事件包装成我们的消息,好这样呢,我们就完成了这两个的粘合,就是将事件转化为消息,这一个步骤呢,那克老师已经帮大家解决了,好那么接下来呢,我们需要解决的一个问题是什么?好,我们的事件怎么跟@进行绑定的呢?啊,我们的。这个网络事件,它是怎么到达这个阿尔当中去的?好,我们来解决第二个问题。好,第二个问题,我们的网络事,网络事件怎么转化为。呃,怎么与?阿进行绑定。
43:04
好,那么我们来思考一下怎么跟他进行绑定呢?好,Mark克老师再来跟大家讲解一下我们的阿的运行流程,阿的运行流程大家可能刚刚又不记得,Mark克老师跟大家介绍一下,这个呢,就是我们的阿的运行实例,对不对?好,我们呢,总共有三个部分构成,第一个是我们隔离的运行环境,我们通常用多R虚拟机来进行实现,好,还有一个消息队列,用来存储先后到达的我们的消息,对不对,好,那么我们在这里面呢,还需要有一个回调函数,对不对?我们将这个消息作为回调函数的参数来运行我们的这个阿,对不对,好,那么接下来我们知道了要去绑定这一个阿,首先呢,我们需要把这个消息发送过去,对不对,好那么还有一个呢,就是我们如果要跟某一个消息进行绑定,肯定是我们去创建这个事件的时候,来与我们的这个来进行绑定,对不对。好,Mark克老师再跟大家说一下,就是我们如果在这个阿当after当中处理网络消息对不对?那么首先呢,我们肯定在这里面要进行有一个设置,对不对,设置到我们网络消息传递过来的时候,我们的这个消息才能够到的它对不对?好,那么我们来看一下这一个模糊的流程是怎么来处理的,好模糊的流程来怎么处理的?好要了解这一个模糊的流程是怎么处理的呢?首先我们需要知道的是什么呢?需要知道我们的E好E是怎么处理的。
44:30
好,那么麦克老师呢,简单的跟大家看一下我们的一的一个原理图。好,稍微等一下,麦克老师呢,截个图给大家看一下。好,大家看到这个呢,是我们的这个E的好具体的处理流程,也就是跟我们的阿绑定的一个处理流程,好首先呢,我们会有啊,一有三个接口,第一个创建。
45:06
E great对不对,Great诶。好,第一个ete。好,Eri的时候呢,它会在我们的Li子内当中呢,创建两个重要的数据结构,第一个呢,是我们的红黑数,第二个呢,是我们的就绪队列,好,那么还有一个呢,我们需要可能要做我们具体的事件的注册,对不对?好,那么显然呢,我们的这一个啊scan的act当中呢,肯定要去注册这个具体的事件,对不对,肯定要去注册具体的事件,那么接下来这个事件呢,才有可能到达我们的这个act,那么注册呢,就是我们的这个啊e control,那马克老师来跟大家讲解一下e control的它的具体处理的流程,当我们去注册一个事件的时候,他会往我们的内核当中的一个红黑数添加一个节点,添加节点的同时会跟我们的网卡驱动建立一个回调,建立一个回调映射关系,好,那么大家看到这个就是我们的这个啊回调函数,好,当我们的网卡驱动检测具体的事件触发的时候,就会去触发我们的这一个回调函数,它会将具体触发的事件拷贝到就绪队列当中来,好接下来呢,我们的用户。
46:16
就会通过事件循环,对不对,事件循环了,事件循环呢,我们会通过一位置从将这个内核当中,将内核当中的这一个就绪队列,也就是准备好的事件,把它拷贝到我们的用户态来,对不对?好,大家看到这个用户态的数组,这个是用户态的数组,它是一个一个的事件,对不对?好,那么这个事件是什么样的类型呢?好,麦克老师跟大家介绍一下这个事件的类型,它是我们的e invent。好,大家能看清楚的朋友帮马克老师好,麦克老师呢,稍微把它放大一点给大家看一下,好这个呢,就是我们的一问,呃1INVENT它有两个结构构成,第一个invent invent呢就是我们注册的具体事件的类型,比如说你要注册读事件,注册写事件,或者是注册其他的事件啊,注册读写事件,那么呢,我们用这一个invent结构呢来进行存储,好那么现在有一个重要的数据就是我们的data,这个data呢。
47:11
就来起到了我们的阿跟我们。跟我们的跟我们的事事件呢,就是我们具体的事件绑定呢,啊起到一个非常关键的作用,就是我们的这个data,这个data呢,它的作用是什么?它主要保存的是关联数据,这个关联数据如何来理解呢?就是比如说我们的某一个阿,它对某一个FD特别感兴趣,那么我们会在这里面呢,调用e control,在这个react当中调用e control,它会去注册这个事件对不对,好注册这个事件,当这个事件经过我们网卡驱动去检测,事件触发,然后通过回调函数将它拷贝到我们的就绪队列对不对,就绪队列又拿到用户层来,好,那么我们就通过这个事件,那么我们的这个事件怎么来知道是这个阿发过来的呢?好,那么这里面最关键的数据就是这个data,这个data塔就是我们把这个数据传递到内核当中,大家注意了,这个黄色的部分是内核当中,好等一下这个事件被触发的时候,内核又原封不动的会这个。
48:16
数据传递回来,这个呢就叫做关联数据,就是我们注册的时候给他携带一个用户数据,好,那么这个事件被触发返回,返回来的时候呢,他又会把这个事件原封不动的返回。到我们的用户层来,这样呢,我们就知道具体它是由哪一个啊,哪一个实体去注册的,这个能听明白的朋友帮麦刷一,那么通常呢,我们能够使用的,大家看到这个data,它是一个联合类型,它是一个联合类型。这个联合类型呢,就是我们在这里面可以选择任意一种,这四种当中任意一种,我们常用的是这两种,第一个FDFD呢,像我们的就是使用的FD好以及。
49:04
好,我们的scan当中呢,是用的这个PDRR啊对,我们是用的PDRRSC当中呢,是使用的这个PDRR。好,那么这个PDR是一个用户的结构对不对?那么这个能理解的朋友帮麦卡老刷这个关联数据,能够理解的朋友帮麦卡老刷一就是我们这一个结构,PDR是我们用户的一个指针,好我们注册的时候把这一个注用户的指针传递到内核当中去,内核检测这个事件被触发之后,它又返回回来了,大家注意了,它不会去修改我们的这个指针,那么这个指针呢,能够直接标识我们具体这个事件是由哪一个对象所触发的对不对,哪一个事件注册的这个事件对不对?好,那么这个PDRR,我们来一依次来看,这个PDRR到底指向一个什么样的结构呢?好,它指向的是我们的这个socket结构。好,这个socket的结构呢,就是马克老师刚刚跟大家说了,我们进行网络编程的封装层面当中有IO检测,IO操作,还有呢就是事件对象封装,那么这一个socket呢,就是指的我们具体事件对象的封装,好这个能听明白的朋友帮马克刷,那么这一个事件对象呢,第一个就是告诉我们它指向了哪一个阿,大家看到第一个字段就告诉我们它是一个ID,它直接指向了我们是哪一个阿,是哪一个阿,好,那么还有这里有一个具体的ID。
50:29
而FDFD呢,就是我们进行网络编程IO操作的时候,Read receive前面的第一个参数FD,对不对,就是文件描述符,这个是文件描述符,好,那么为什么在这里面还有一个ID呢?好,我们的scanner呢,进行了一个优化,优化什么呢?因为我们的这个事件对象,它可能会要频繁的创建。啊,它会要进行频繁的创建,所以呢,我们的scanner只在这里面设计了一个对象池,这个呢就是我们的socket事件对象的值,那么事件对象的值呢,我们是怎么进行分配的呢?啊,我们分配一个可用的事件对象的时候,它以ID的方式来告诉我们,这个ID呢,就是我们的这个事件对象池的索引ID,因为我们的这个实事结构呢,它是从零开始的一个数组,对不对,这个ID呢,就是我们的这个具体的索引ID,好,这个能听明白的朋友帮麦克老师阿姨,那么现在麦克老师再跟大家来讲解一下我们的网络事件是怎么跟阿进行绑定的,里面有一个非常关键的因素,就是我们的事件1ONE当中的这个data,也就是我们的这个关联数据,好,麦克老师呢,再跟大家来梳理一下,我们这个事件从产从注册到产生,怎么跟我们的阿进行绑定的。好,首先。
51:50
我们的阿业务逻辑当中,首先需要去注册具体的网络事件。用哪个接口进行注册,通过control进行注册,注册的时候我们会把这个e invent把它写到写到这个红黑数当中,好写到红黑数的时候,同时跟我们的网卡驱动建立了回调映射关系,当我们的当我们的这一个网卡驱动啊触检测到这个事件被触发了之后,那么我们会调用这个回调函数,这个回调函数会将这一个红黑数具体触发的红黑数的这一个节点拷贝到我们的就绪队列当中来,就绪队列当中来,那么接下来呢,我们的用户层,用户层呢会通过一个组,通过事件循环的方式,事件循环也就是通过一位置的方式,会从就绪队列当中的数据拷贝到我们的用户当中来,拷贝到我们的用户态当中来,那么此时用户态当中的这一个数组就会呃,接收了多个被触发的网络事件,那么这个网络事件呢,我们会从中可以拿到我们的这个啊关。
52:58
联数据好,通过这个关联数据,我们就知道是指向的具体的哪一个结构,这个能听明白不把马卡刷阿一好,这个从用户层到我们的啊,内核态啊,用户态到内核态,再从内核态到用户态的一个整个流程啊,就完成了,我们这个网络消息是怎么跟我们的阿进行绑定的。
53:24
好,这个绑定关系我们了解了之后呢,迈克老师大家只看到了一个原理,没有看到原码对不对?好,迈克老师来跟大家来介绍一下这个里面的原理。好,我们来跟跟大家来看一下我们的这个代码的具体的流程,首先呢,我们走到这个。好一好,我们首先刚刚麦克老师跟大家说了,对不对,我们spr的就是去注册事件对不对,好,注册事件的时候,这里面有一个PDRR,好PDRPDRR的这里会传递我们具体的,呃,事件对象对不对?好我们来看一下哪里调用了SSPR的,好大家看到这里面呢,调用了SDR的。
54:05
好,SBR的这个S是什么?这个S是我们的这个搜值对象,这个能听明白的朋友帮麦刷一,这个呢是我们的对象事件对象值,从事件对象值当中取出一个事件,把这个事件呢,作为第四个参数传递到spr的当中,好spr的呢,会调用我们的e controltl2的对不对,也就是网红分数当中写数据,好那么此时呢,我们会把用户态的一个数据呢,传递到内核当中去,对不对,传递到内核当中去,好接下来我们就通过一个事件循环,这个就是我们的事件循环的封装事件循环,我们从一位置当中,从就绪队列当中,把这些旧绪的事件呢取出来对不对?取出来的时候,我们是不是可以通过这个PDRR,大家要PDRRPDRR就是我们刚刚传递的这个事件对象的结构对不对,好,也就是这个S,好,那么SP位置呢,在上层是怎么取出来的呢?好,马克老师给大家看一下,好,那么大家可以看到这里面呢,我们就会从啊取出事件了,取出事件接下来我们是不是就可以取出这个。
55:06
一个具体的sockage的对象,好取出sock对象之后,我们就可以把就知道具体是往哪一个阿发送消息了,对不对,这个事件刚刚转化为消息,然后再将消息发送到阿,好,我们看一下这个流程,好比如说我们这里面呢,是一个读事件,好,我们来看一下这个流程。好,大家可以看到这里面呢,我们会知道一个s.OP啊,大家看到。这里是不是OB,它是指向具体的阿,对不对,指向具体的阿,好,我们把这个具体的阿,把它赋值给我们具体的这一个网络消息啊,赋值给网络消息,那么接下来我们就可以把这个消息发送出去,好迈克老师再跟大家跟一下这个流程。好,我们呢,这个SD位置。好在上传的时候呢,我们会把这个消息发送出去,对不对啊,大家可以看到我们拿到这个消息,好,那么接下来呢,要发送到我们的。
56:07
消息队列当中去,好,那么大家可以看一下这个scan cantest push,这个呢,就是往我们的act当消息队列当中去插入一条消息,这个能听明白的朋友帮帮老师,往消息队列当中插入消息这个result是不是我们刚刚从这一个S事件对象当中赋给他的赋值给他的这一个啊阿的ID对不对,我们通过这一个消息队列的ID找到了我们这个阿,好,我们塞到了这个阿的当中的消息队列,好这个能听明白的朋友帮马克老师阿姨,这个代码的流程呢,Mark克老师也跟大家跟了一遍,对不对?好,接下来我们再来跟大家来看一下携程是如何将异步操作转化为同步的操作。好,那么异步操作跟同步操作是什么意思呢?
57:01
好,那么马克老师跟大家举一个例子。好,这个呢,涉及到一个网络编程的一些,首先麦克老师跟大家介绍一个网络编程的一个思路啊,网络编程。好,React的网络编程好,那么这里面呢,涉及到一个细节,好麦克老师来跟大家说一下react网络编程当中啊,我们的数据的到达。是怎么处理了的?处理流程?好,那老师把这个流程跟大家说清楚之后,再来跟大家来介绍我们的治理是怎么处理的,就是我们怎么将异步操作转化为同步的操作。好,那么首先呢,我们来看一下这个数据的到达的处理的流程。好,那么通常我们新建一条连接的时候,就是我们接收到客户端的好,麦克老师跟大家说一下,当我们收到收到我们呃,客户端的连接的时候,好,那么呢,我们会用。
58:05
好,这里呢,我们会拿到一个clientd CD呢会通过accept。好,通过这个FD。好,这里呢,跟S。好,麦克老师跟大家说一下,这个接口就是当我们接收到客户端的连接,接收到客户端连接,它通常是我们只listen fd有读事件被触发了,毒事件被触发就是我们的呃,IO检测,IO检测检测到我们的listen fd有毒事件,那么呢,接下来我们就会调用接收这个客户端的连接,对不对?怎么接收客户端的连接呢?我们通过的接口好用this fd address跟size clientd来接收我们的这个客户端的连接,好这个clientd呢,是指我们具体的客户端的。啊文件描述符,那么address跟size是什么意思呢?好这个呢是我们具体客户端的啊原I地址,IP地址跟端口,IP地址跟端口,这个能听明白的朋友帮忙卡刷一,这里面呢,这一个接口给了我们两个信息,第一个信息拿到了一个具体客户端的IDFD文件描述符,第二个我们拿到了这个客户端的具体的ID跟端口,好它是从哪个地方来的,我们是知道的,好那么第二步呢,我们接下来就会设置好注册客户端连接的读事件。
59:26
好,注册客户端FD的读事件。好,也就是我们通过e control对不对,我们通过e controll去注册这个事件,我们接下来呢,会对这个客户端的FD的读事件的感兴趣,对不对,好,那么这里面呢,有EFD,然后呢,后面我就不写了吧,反正呢,我们要去注册一个读事件,也就是我们e in啊e in好,第三个当我们的客户端给我们的服务器,也就是我们的react网络模型啊,发送消息的时候,这个时候呢,我们呃在事件循环当中。
60:04
好,在事情循环中,我们会收到。好,我们会收到这个扣单FD,好,我们用D,我们收到plan fd的读事件触发。好,当我们的客户端的读事件触发的时候,大家注意了,这个事件循环,它是在我们的一位置当中去处理的,对不对,好一位置。好,这个位置当中检测到这个FD的读事件触发之后呢,接下来我们就要进行IO操作了,大家注意啊,接下来我们会进行IO操作,好,那么我们会调用好调用read的。好,我们来写一下,N等于read f plant of d好,我们的buffer size,好,麦克老师跟大家介绍一下,接下来呢,我们就会调用IO操作,IO操作就是去从我们的内核当中去读,读取这个FD所对应的读缓中去啊孟老师把这个图也给大家画一下,好,这个呢是上面呢是我们的用户肽,好下面呢是我们的内核肽,好下面是内核肽。
61:17
好,这个是用户态。好,这个呢,是我们的内核肽。好,那么接下来呢,就是我们每一条连接,它都会对应着一个读缓中区,好这个呢是read的好,它内核当中会有一个读缓冲区,好我们的调用这一个接口呢,其实它是一个系统调用,对不对?好我们在这里还写一遍吧,好,Int n等于RA的fd size。好,那么实际上呢,就是我们用户他会准备一个好准备一个这样的buffer,好用来接收我们的读管中区当中的数据,对不对,好,也就是我们会从用户态当中从。
62:04
好,这里面的数据呢,拷贝到我们这个B法当中来,好这个呢是我们预期要读的数据,我们预期要读这么多数据,那么实际读取的数据呢,是这个N好这个能听明白的朋友帮老刷好这个呢就是我们数据到达的一个处理的流程,这个就是从react网络编程的角度出发,好这里面呢涉及到IO检测啊,IO检测第一个呢,IO事件的控制,事件控制我们需要调用e control,好去注册这个CDCD的C,呃,CD的读事件,好注册完之后呢,我们就会在事件循环当中检测到这一个客户端连接的呃读事件,当检测到它读事件触发的时候,说明这一个它的读缓中区当中有数据了,好,也就是我们的客户端点服务器发送数据了,我们的读缓冲区这一条连接所对应的读缓冲区有数据了,接下来呢,我们就用。
63:03
这个IO操作,这个IO操作呢,就是read read呢从内核态当中的读款中去把它拷贝到将数据拷贝到我们的用户态来,好,这个能听明白的朋友帮麦老师阿姨好,我们知道这个流程之后呢。这个呢,就是我们react网络编程的一个主要的流程,好,那么大家来思考一下。我们这个read的,刚刚麦克老师也跟大家说了,我们数据到达在用户层啊,我们来找到这一个冲突点,看大家能不能找到这个冲突点,就是我们刚刚跟大家说就说了数据到达的封装,我们通常要做哪做哪两层封装呢?第一层封装好,第一层封装我们需要封装读固定字结束。好,看看大家能不能找到这个冲突点,第二个呢,好读分割字符对不对?好,我们为什么要做这两层封装呢?好。
64:03
好,为什么要做这两层封装呢?好,因为我们数据到达,接下来就是要做业务逻辑,这个能听明白的朋友帮帮老师阿姨好,做业务逻辑首先要解决的问题是什么?界定数据包对不对?好界定数据包什么?我们通常界定数据包有哪几种方式呢?也就是我们通常所说的拆包和粘包。好拆包啊,拎包对不对?好怎么处理拆包和粘包对不对?好,也就是我们要界定数据包,界定数据包呢,通常我们要么这个数据包呢,是我们用户定义的,就是我们定义这一个前面有一个头指向着我们整个数据包有多长,好那么还有一个呢,就是整个数据包当中呢,我们会有一个特殊字符来进行分割,比如说一-N那么呢,这里面就是我们有意义的一个数据包,好那么呢,所以呢,我们进行封装的时候呢,要封装这两个接口,好上面的这个呢,是我们的react网络编程。
65:03
网络编程当中的一个具体的流程,好,那么我们刚刚麦老师也跟大家讲解了这个具体语句的含义,对不对,就是我们预期从内阁当中读取size子这么多数据对不对,我们预期实际呢,读取的是N对不对,所以呢,我们的N。所以我们的N是小于等于S的,对不对?小于等于S的好,那么我们通常是怎么封装这两个接口的呢?好,我们首先来看一下scanner是怎么封装的。好,大家可以看到我们呢,有这么几个接口,好so.read。好,这个呢,就是我们第一层封装。好,我们随便截个图。好,这个呢是读固定字节数,大家注意啊,这个是我们用户读出来的,用户读的。好,第二个呢,是我们的read read line。好,这个呢,是我们的第二个接口。
66:04
好,第二个层次的接口。好,这个是第一个接口,这个呢是第二个接口,好,问题来了,现在问题来了,大家不知道已经有没有考虑到他们的冲突点,冲突点就是我们通过这一个系统调用,不能够确保我们一定能够读到这个size的长度,这个能听明白的朋友帮马卡刷一,我们不能通过一个read确保它通过一次IO操作就能够把我们所需要读取的固定字节数呢一定读取出来。这个能听明白的朋友帮麦克老师刷一,那么呢,我们通过这个接口更加不能够确定我们是不是读到了一个分割符,这个能听明白的朋友帮麦克老师刷一。好,那么现在这个呢,是我们用户层的,这个是我们用户层的调用接口,这个是用户层调用的接口,上面呢,是我们啊事件驱动的方式,因为我们的react网络编程,它是一个异步事件的一个框架,对不对,异步事件的框架它呢是这样的一个处理流程,好那么我们怎么把这两个流程进行粘合。
67:11
好,麦克老师跟大家说一下。好,我们用方框框把它框起来吧,让大家知道这个呢是我们的事件驱动流程,我们来写一下。好,这个是事件。好,这个是事件驱动流程。好,下面的这个呢。啊,我们这个图截的太大了,我们来给它小一点。啊,我们这个图截的太大了。好,那老师重新截一下,重新截一下,截小一点好给他呢,这个是我们的业务流程啊,随便截小一点。
68:13
好,这个呢,麦克老师来跟大家说一下,这个呢是指我们的业务流程。好,这个能听明白的朋友帮忙看刷一个呢是事件驱动流程,就是我们网络当中到达数据了,这个呢是我们的react的数据到达的时候的一个啊标准的处理流程,好这个呢是我们的业务需要处理的流,处理的流程就是我们一定要读这么多的数据,那么呢,我们接下来就开始解包了,对不对,好去去进行解包,然后再开展具体的业务逻辑了,好要么呢,就是去读固定的字符串的读。呃,分割符对不对,比如说这个是杠N,那么我们要读到这里结束对不对?好,那么大家知道的冲突点在哪里呢?冲突点就是我们的业务流程跟我们的事件驱动流程当中,主要是指我们的这个read的,我们预期读size这么多数据实际读的是N,所以我们不能够确保好我们在这里面呢,能够在事件驱动流程当中呢去。
69:15
来解决我们的这两个接口的问题,对不对,好那么我们呢,在这里面主要用携程来解决,好用携程进行解决。好,那么我们来看一下怎么用携程进行解决呢?好,那么首先我们从这一个携程的运行出发,来帮助大家来理解一下我们撸R当中的携程,好,R当中的携程,首先让大家来了解一下路R的携程。啊,我们把这个图呢,稍微放小一点,截出来帮大家来理解一下,这个呢是路啊携程。好,把这个图截一下。好,这个呢是路尔携程那克老师一个个跟大家介绍,首先我们在路尔携程当中呢,会有一个ing great创建一个携程,好携程呢跟我们的线程是差不多的,对不对,因为携程是一个轻量级的线程,好那么线程的函数p red great对不对?P red great它是不是也有一个入口函数,那么我们的携程呢,也需要有一个入口函数,那么这个匿名函数呢,就是我们的入口函数,那么这个入口函数当中呢,大家需要注意的是,我们这个携程创建的时候,它会自动将我们的创建的这个携程,这个携程挂起来,首先它会挂起来,接下来呢,我们这个呢,是我们的主携程,好主携程这个主携程呢会在这里运行,首先我们调用第一个proing resume的时候,就是唤醒,携程怎么唤醒呢?好,这个是自动挂起的,那么我们会怎么来进行调用的流程呢?我们会把这个 Rg11好传递给我们。
70:58
的这个方式就是我们的这个入口函数的参数,好把这个参数传递给他,好,那么接下来呢,我们就会开始往下面运行我们的这个子携程,大家注意了,当我们在主携程当中去唤醒其他携程的时候,那么此时呢,我们的主携程挂起来了,好,主携程挂起,因为呢,在路R当中同时只能有一个携程在运行在路R虚拟机当中。
71:24
同时,只能有一个携程在运行。好,所以呢,我们此时它运行的好,那么就是我们的主携程挂挂起来了,然后呢,去唤醒我们的子携程,好,那么我们把这个R级C1传递点R级11对不对?好那么我们接下来往下运行好,接下来呢,我们的子携程当中定yard的,它呢会让我们的子携程挂起啊,这里呢,会子携程挂起。
72:01
好,它挂起之后大家注意了,它挂起的时候,我们会把这一个参数传递到刚刚好,它挂起的时候呢,我们的主携程又会唤醒,它又会唤醒我们的主携程调度携程,好,它会把这个参数传递给我们的这个的返回值,好right t好接下来呢,我们的主携程又往下运行,好,主携程往下运行,然后我们再调用这一个换行,因为我们子斜程已经挂起来了,对不对,好,我们的主斜程呢,又去唤醒它怎么唤醒好,我们会把这一个参数会作为要的的返回值,好那么二二就是我们刚刚传递给的RA1啊,RA一会传递给这个R2,好,然后我们此时呢,主协程又挂起来了,它又挂起来了,然后我们现在呢,又来运行我们的子斜程,子斜程此时我们就出去了,Return出去的值,Return出去的值,它会返回给我们的这个好。
73:01
返回给我们的主携程的返回值,好,这个right好,大家可以看到我们的数据传来传去,那个老师再来说一遍,好,这个呢,刚刚创起的携程,它会挂起来,自动挂起来,那么怎么去运行它呢?我们需要调用resume好去唤醒携程,唤醒携程的时候呢,它会去唤醒子携程,同时把自己挂起来好,那么参数是怎么传递的呢?我们resume的参数会传递给这个函数的函数的入口,函数的这个参数好,那么子携程运行的时候呢,它有一个专门挂起的一个语句,就是要的要的呢,这一个参数它会传递给它的返回值好,传递给它的返回值,接下来呢,它挂起来了,子携程挂起主携程在运行,运行的过程当中,我们就会把这个RA1,我们又resume好主携程挂起,又去唤醒子携程,我们的RIGHT1会给这一个啊二级二好,二级二呢,运行的过程当中,它会把RIGHT2返回出来,RIGHT2呢又会返回给。
74:01
这个resume刚刚挂起的主携程挂起的地方,好,返回给这个writer好,那么呢,接下来就是这个整个流程,就是我们的携程运行的流程,好那么现在问题来了。那么现在运行来了,而问题来了。大家思考一下,我们在业务流程当中去调用这两个接口的时候,是不是能够确保socket read是100%能够读到这么size的数据,对不对,这肯定是能够保证的,对不对?那么这个sockage read line呢,肯定能够保证我们恰好读到了一个杠啊杠N结尾的这样的一个字符串,好那么大家就注意了,这个呢,肯定能够读一个固定字节的数,好,它会返回的,好那么这里面呢,也肯定能够返回出以杠N结尾的这个值出来,好那么现在问题来了。我们现在显然要通过携程来处理这个事情,为什么呢?好,我们以这个为例子,好,这个是案例一,这个呢是案例二,我们以案例一为例跟大家来进行解释,假设我们现在要读1000个字节,假设我们现在要从网络缓冲区当中读1000个字节,但是呢,此时我们的读管中区当中只有50个字节,好,只有50个字节。
75:20
那么此时我们这里是不是应该挂起,因为我们的这一个接口是一定要读1000个字节的,现在我们的读管中区当中只有50个字节,那么现在呢,我们这里面就要挂起来,对不对,好好要挂起来,是不是我们要调用这个Y的对不对?Y的就是让我们的这个携程挂起来。好,挂起来,那么什么时候唤醒它呢?什么时候唤醒它呢?好,大家注意,我们的这个流程应该是这样子的,对不对,我们要读1000个字节,但是呢,我们此时只有50个字节,那么呃,我们在在挂起之前,我们要记录一下,我们等一下唤醒的条件,我们在这里面是不是要记录一下唤醒的条件,也就是说我们要在读缓中区当中有1000个字节的时候,你再用其他的携程来把我唤醒吧,对不对,唤醒的时候呢,我们就可以在这里面正好返回一个1000字节的数据,好,这个能听明白的朋友帮马克老师阿姨,好,那么现在马克老师要有问题要问大家了。
76:22
那么大家思考一下,这个呢,是我们的业务流程好,那么。大家思考一下我们的这个有哪一个携程来把我们唤醒呢?好,能听懂问题的朋友帮忙刷一,就是这个是我们的业务流程,我们现在要读1000个字节,但是呢,此时我们只有50个字节,那么显然呢,我们要在这个接口的里面把携程挂起来,对不对,携程挂起来,那么我们。需要在什么流程当中把我们的这个携程唤醒呢?是不是应该要在事件驱动流程当中把我们的这个携程唤醒,唤醒啊,去唤醒对不对?好,麦克老师给大家看一下。
77:08
因为我们的事件驱动流程当中,它会不断的去检测这个事件,好它会呢,当我们的毒事件触发的时候,我们会去填充这个读缓冲区,对不对,会去读填充缓冲区,那么我们在这里面呢?因为我们刚刚挂起的时候记录了一个条件,就是要要1000个字节我们才能够唤醒,那么呢,我们是不是在这里面判断一下就行了,我们在这个事件驱动流程当中去去判断,判断这个buffer的长度是不是现在是不是有1000,好如果有1000的话,我们就把这个流程唤醒,那么这样子我们这个接口是不是就实现了,好这个能听明白的朋友帮麦克老师二一。好,那个老师再跟大家讲一下,在业务流程当中,我们要实现这两个接口,好实现这两个接口,那么呢,按照我们的这个事件驱动流程当中,我们在这里面去读数据。
78:05
很难去保证这两个接口,因为呢,这个是我们预期读到的值,这个是我们实际读到的值,也就是说我们不能够保证我们一定能够读到这个size的值,因为呢,我们通常得取出来的结果,这个N是小于等于等于size的,对不对?好那么如果我们要实现这么一个流程呢?那么我们可以利用来斜程的方式,利用携程的方式,怎么利用呢?好,那么我们假设我们要读1000个字节,那么此时里面只有50个字节,那么我们记录一下我们要读1000个字节的条件,好满足这个条件我们就把我唤醒,好,那么我们在这里面呢,让出我们的携程,然后呢,在事件驱动流程当中,好去填充我们的读缓冲区,我们填充读缓冲区的时候,当满足1000的条件,我们就把这一个携程唤醒。好,这个流程能听明白的朋友帮麦克老师阿姨,好,如果能听明白的朋友呢,麦克老师接下来就带领大家看一下语码,来帮助大家理解一下这个流程。
79:04
好,这个流程怎么来看呢?这个流程怎么来看呢?好,首先我们来从这一个socket点路啊,从这一个接口出发。好,那么大家可以看到这个呢,是socket read对不对,Sockage read sockage read呢,那么我们首先从。啊,我们尝试去读1000个字节,我们就以千个字节为例,好假设呢,我们现在去读1000个字节,好,那么我们发现呢,恰好有1000个字节,假设我们呢,恰好发现有1000个字节啊,大家看到这个呢,是我们读取的数啊这里啊假设呢,我们假设恰好有1000个字节,那么我们就直接return出去了,好直接出去了,但是如果我们没有不满足条件,不满足条件呢,我们就需要记录一个值。哎,是不是瑞的是这里。好在这里在下面这里看错了,好大家看到我们呢。
80:01
首先尝试去读这一个好,尝试去读这一个size子的数据,好,假设我们读到了这么多数据,我们就直接返回,如果我们的读缓程序当中它有1000个数据,那么我们直接返回,好,没有的话,那么我们就要记录这一个唤醒的条件,这个就是我们记录唤醒的条件,Read的require,我们记录一下我们唤醒我的条件是什么,好,那么就是读1000个字节,好,接下来呢,我们就进行挂起好,这个呢,就把我们当时此时的流程挂起来了。好,大家看到我们会调用一个scan weight,好,Scan呢就会去调用。我们的要。好,大家看到它实际上调用的就是我们的suspend sleep对不对,好,Suspend sleep呢就是对不对,它就是挂起我们的携程。好,挂起携程之后,我们接下来要到事件循环当中,事件流程当中,事件驱动流程当中,对不对?好,接下来我们来跟大家跟一下我们的事件驱动流程,怎么把事件驱动流程去把它唤醒的,好麦克老师跟大家看一下这个流程,好事件驱动流程怎么看呢?当然从我们的C语言出发,对不对?
81:15
好,那么我们呢,首先在这个事件循环当中去找读事件,好怎么去找读事件呢?读事件就是我们的soage data,对不对?刚刚马克老师也跟大家说了,我们的封装事件的到达,事件的到达是这一个socket data,它对应的是我们的事件的到达对不对?好事件的到达呢,它会有一个forward message啊,我们来看一下forward message。好,For message呢,我们这个result已经填充好了,填充好了之后我们就会要push到message当中去,对不对。好,大家是否还记得刚刚迈克老师跟大家讲解的阿是怎么运行的,阿的运行是我们把消息发送到消息队列当中,对不对?好,消息队列当中呢?我们会有回调函数,回调函数呢?我们会把消息作为参数传递给回调函数,通过这种方式呢,我们来运行阿,对不对?好,那么接下来我们是不是去找这个回调函数,好,我们知道已经push到消息队列了,好,那么我们找到这个回调函数,我们就知道在哪里运行了,对不对,好,那么麦克老师在这里面需要给大家来介绍一下scanch点路啊当中我们有一个scanch star在这里面呢,会去。
82:27
设置我们的回调函数,这个呢就是我们的回调函数,看到这个回调函数的朋友帮老11好,这个是回调函数呢,但是它不是我们socket,就网络消息的回调,这个呢,是我们的这一个阿的入口函数,但是呢,我们有根据不同类型的消息,我们有阿之间的消息,有网络消息,有定时消息,对不对?好,那么我们来找一下网络消息是怎么处理的,网络消息呢?我们是在这里进行注册的,好register pro。好,大家看到这个呢,就是网络消息的回调,Dispar就是我们网络消息的回调,好网络消息呢,它就是好通过socket message来进行处理的好socket message呢,我们可以看到这里面有很多soet message,它都是我们的一个函数,好我们找到这个读事件触发的消息,好这个是我们事件触发的消息,它会回调到这里,好回到到这里之后我们来看一下。
83:28
Read Perry是不是我们刚刚记录,刚刚我们有一个读数据的这一个携程挂起来了,对不对,挂起来它的条件是什么呢?什么条件唤醒它呢?就是我们的这个read query read query呢,它记录的是具体的长度对不对,具体的长度那么呢,也就是我们的这个R啊好,那么大家看到这个的朋友帮马克老阿一看到这个的朋友帮麦克老,这个是从网络当中读取的数据,这个size,当我们的这个size大于等于我们刚刚挂起的条件是不是?
84:02
满足这个if判断语句,就是满足了我们的条件,满足了条件是不是要去唤醒我们刚刚的这个携程,好,我们这个wakeup就是去唤醒。好,Scan wakeup呢,它就是调用的resume,大家看到它调用的就是我们的scan resume。好,它调用的就是我们的standard resume,大家可以去查找一下,我们先。了解一下就行了,这个wakeup。好,Wakeup就是调用的,我们把我们刚刚挂起的携程唤醒了,那么接下来呢,我们的scan。点read,好,那么呢,我们携程呢,就在这里唤醒了,唤醒了之后我们就会把我们所需要的数据呢返回出去了,好这个能听明白的朋友帮麦克老师阿。这个呢,麦克老师就把这几个问题呢,都跟大家解释清楚了,就是携程是怎么将异步操作转化为同步的,好那么大家需要注意的是我们的这个事件驱动流程当中,这里面呢,全是回调啊,全是回调,那么大家可以看到。
85:15
我们的这一个接口是不是也是一个同步的操作,它是不是一个同步的操作,我们同步读取这么多数据,实际内部呢,它是一个异步的流,异步驱动的流程,对不对?好,它是一个非阻塞的一个异步驱动的流程,好。这个就是说的同步非阻塞。啊,我们这节课的主要的内容呢,先跟大家介绍到这了,就是主要跟大家介绍的我们的scan网络模块的封装,那么大家呢,需要了解的是我们的scanner是什么?它是一个阿的并发编程模型,也就是在我们的用户层去抽象很多的进程,那么这些进程呢?这些进程它是以消息通过消息之间进行交互的,来驱动我们阿的逻辑的运行的好,那么我们的携程的作用是什么呢?携程就是我们需要在里面写一个同步的代码,好如果我们光只有一个消息,那么呢,会把我们的这个scan编程呢,陷入一个回调陷阱,回调陷阱对不对?所以呢,我们在这里面会使用这几种。
86:23
好,那么大家需要了解的是,不管大家掌不掌握我们的scan,那么大家都需要知道我们的react网络模型通常是怎么进行封装,那么呢,我们通常要封装三个层次,第一个IO检测,第二个IO操作,第三个我们要封装事件的对象好,对于IO操作而言,我们要封装封装事件的控制,也就是注册好,注销以及更改对不对,修改我们的事件好。那么还有一个就是事件循环,通过一泡位置当中把事件取出来,接下来呢,事件循环当中取出就绪的事件呢,接下来就是。
87:01
依照每一个事件去做IO操作,那么我们IO操作,我们封装要封装哪些内容呢?好,连接的建立,连接的断开,这个呢,标识着一个对象的生命周期,我们还要处理消息的到达以及消息的发送完毕,好,那么我们分别需要注意这里面所需要处理的啊,处理的内容。大家需要关注。好,那么我们是怎么scan呢?是由这三个关键字构成的,我们的react网络模型呢,是由这两个关键字构成的,那么我们这五个之间是怎么起化学作用的呢?好,那么我们首先需要将事件转化为消息,然后呢,由消息去驱动我们阿的运行,对不对?好消息驱动阿的运行呢?它会进入一个异步回调,对不对?好,我们通过携程去消除这个异步回调,那么最终达到的一个就是我们编程的时候是一个同步非阻塞的好。那么这节课呢,主要的内容呢,就跟大家介绍到,那到这大家等一会儿需要我们这一份文档的朋友可以加一下我们秋香老师的微信啊,那么在这里面呢,也跟大家介绍一下,就是在我们的VIP课程当中呢,我们会更加详细的帮助大家来学习我们的这个网络模块的封装,那么我们呢。
88:18
会从四个层面跟大家来介绍这个网络模块的封装。第一个层面,好的封装。好,也就是我们scan呢,它也是一个单react,好,那么还有一个呢,就是多react。多react呢,就是我们一个多线程的处理,多线程或者是一个多进程的一个封装好,第三个就是我们会去基于这个阿。好基于这个react网络模型,好去实现异步连接,好第四个呢,我们会带领大家去实现一个好携程消除回调,好基于。
89:05
好,那么我们呢,大家如果啊有机会加入我们的VIP课程,那么呢,大家会对这个网络编程当中所有出现复杂的问题呢,大家都能够呃,手把手,大家都能够去学习这些编程的流程,刚刚马老师是不是只是介绍了一个网络事件驱动流程当中的数据到达的处理流程对不对?好,还有连接的流程,还有一个呢,半关闭状态的流程对不对,处理流程。好,麦克老师简单的跟大家介绍一下半关闭状态,好,我们就下课了好吗?好,半关闭状态是什么意思呢?好也就是顾名思义就是我们允许关闭一个端口,对不对,好,那么它对应的流程是什么呢?对应的流程是我们的四字挥手对不对?好,左边是我们的客户端。右边呢,是我们的服务器,好,那么我们呢,啊,客户端发送find的包对不对,那么服务器呢,这边会收到read等于零对不对,好read等于零,那么大家需要注意的是,那么此时read等于零,它只是说明好我们的独端关,服务端的独端关闭了,那么接下来呢,我们这里面会。
90:13
好,把这个这个是我们的find的包好,这个呢是我们的HK包好,那么接下来呢,我们服务端的独端关闭了,但是呢,我们还可以给客户端发送数据,对不对,还可以在这个期间还可以继续发送数据。好,继续发送数据,当我们把数据全部发送完之后呢,那么我们又会给客户端发送一个翻包,对不对?好,那么大家注意了这里呢,读端的关闭,当我们在这里面调用close或者是调用刷车档的时候,好,我们把写端也关闭了,当读写端都关闭的时候,我们的E就会收到了一个e hummp好,就会收到一个hummp,好,那么我们通常所说的半连接的半关闭状态的处理呢?就是处理这一段流程怎么处理的。
91:01
好,那么好,由于时间的关系呢,麦克老师就不跟大家介绍这里面的处理流程了,好,那么大家呢,需要我们这篇整节课的文档的朋友呢,可以加一下我们的秋香老师的微信,好,我们这节课呢介绍到这,谢谢大家。
我来说两句