2020/01/16 04-IO多路复用版群聊实现

在这里插入图片描述在这里插入图片描述
用select完成了对事件的监听,由它来监听关注的事件,但凡监控的某一个socket上面事件发生后,select就会结束阻塞,我们就会遍历拿到的这个列表,就可以找到发生的指定对象都是谁。
如果要做操作,就可以在主从的时候传入data(类,对象,方法都可以)

注册的时候,返回一个selectkey,里面包含4个信息
fileobj 关注的socket文件对象
fd 文件描述符
events 关注哪些事件
data 传入数据

只能关注读和写
在这里插入图片描述在这里插入图片描述在这里插入图片描述

官方建议选择非阻塞IO在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
现在,accept和read的时候定义要一致在这里插入图片描述
定义的参数只有一个在这里插入图片描述
这样定义就只适合accept传入,recv就直接报错 了在这里插入图片描述
传参数可以传,但用不用无所谓,避免报错在这里插入图片描述
现在只有一个线程,调用select,主线程就阻塞了,主线程就什么事情都做不了,把select函数扔到其他线程去跑,主线程就腾出来了在这里插入图片描述
官方建议setblocking(False)选择非阻塞方式
在这里插入图片描述
现在的问题是,现在只有这边让主线程阻塞,
在这里插入图片描述
按照道理recv和accept都是阻塞函数,本身这两个也是阻塞行为,但是我们调用的时候已经ready了,数据已经有了,recv就不需要等了,本身是阻塞行为,因为通知它的时候数据已经准备好了,直接拿即可在这里插入图片描述
所以现在是否阻塞是没有影响的,调用的时候已经准备好了
在这里插入图片描述
多路复用的图,上半部分ready才通知下半部分来拿
在这里插入图片描述
把selectt扔到一个函数里去,开启多线程,把select阻塞的扔到线程里去跑
在这里插入图片描述
定义的东西都可以往下放
在这里插入图片描述
使用一下event
在这里插入图片描述
quit退出
在这里插入图片描述
链接一下
在这里插入图片描述在这里插入图片描述
mapping其实指的就是映射。key value的映射,是类字典的
在这里插入图片描述在这里插入图片描述
一个是fds,一个是selectorkeys在这里插入图片描述
遍历出的其实就是当下正在监控的哪些IO

重新链接一下
在这里插入图片描述
一个是socket accept,一个是conn在这里插入图片描述
所以通过get_map方法遍历之后,就可以把东西拿出来了在这里插入图片描述
现在退出可以拿到的对象有,select可以拿到,event需要处理一下(用几个socket,就需要清理几个socket)
现在就反注册

在这里插入图片描述
socket需要关一下,1。清理,链接,2.把fd交还给操作系统,复用一下
在这里插入图片描述
但是这样注册的时候生成map,在反注册的时候,看着是没有pop,但是别人想从kv卸除

链接发送消息
在这里插入图片描述
敲quit这一句就出现了问题在这里插入图片描述
反注册就需要先记录下来,然后资源关闭
在这里插入图片描述
selector.close才可以清理干净在这里插入图片描述
要把所有用的socket全部清除掉,也就是反注册掉,不要监控了,然后把socket该 关关了,所以quit的时候需要做的事情比较多在这里插入图片描述
所以在这里相当于做一个列表解析式,反注册fileobj在这里插入图片描述
这样就做到了资源一部分清理,因为结束和使用并不在一个线程里,无法使用with语法
在这里插入图片描述
现在就正常退出了
在这里插入图片描述

再次演化,更改需求,能否借助IO多路复用来完成项目

在这里插入图片描述
给一个selector,server里自己使用,新的serversocket和每一次新创建的socket在这里插入图片描述
现在需要注册。,起个线程交给select来处理,也需要出处理一个select函数

在这里插入图片描述
现在监听注册在sever。socket上,注册完之后立马开始工作,因为会阻塞当前线程,选择扔到另一个线程里做在这里插入图片描述
想要socket自己传进去
在这里插入图片描述
如果有人accept链接,不再阻塞后,拿到的key.data就是accept,accept传入fileobjet在这里插入图片描述拿到的key.data就是accept,accept传入fileobjet传入就是socket在这里插入图片描述
**注册conn,读世界EVENT_READ,data=self.recv **在这里插入图片描述
现在也不需要这个判断了,因为selector帮你做了
在这里插入图片描述在这里插入图片描述
紧接关注的是recv,收到消息后,就反注册conn
在这里插入图片描述
stop需要循环去清理在这里插入图片描述
下面就需要看一对多的问题,每次accept进来就会生成新的conn,以前一对多的时候需要记录一下,现在self.clients是不保留的。
以前把所有的socket内容保存下容器里

在这里插入图片描述
现在从get_map里去拿,除了conn,还可以拿到accept所在的socket也可以拿到
在这里插入图片描述
通过data判断谁是谁在这里插入图片描述
先遍历,有可能混入self.socket,需要进行判断
在这里插入图片描述
这样判断就区分开来了,两个函数的==就相当于is
在这里插入图片描述在这里插入图片描述在这里插入图片描述
清理一下代码
在这里插入图片描述在这里插入图片描述在这里插入图片描述
首先先需要用这个selector监控socket,这个soscket是用来接收链接的accept在这里插入图片描述
在监听的上面进行等待,不阻塞后就开始进行操作在这里插入图片描述
不阻塞后就开始进行操作在这里插入图片描述
accept拿到这些连接后可以拿到新的链接
在这里插入图片描述
这个链接不要就可以反注册,recv结束,在get_map就找不到了
在这里插入图片描述
关闭的时候,get_map可以拿到所有关闭的socket,反注册相当于从map里把kv对去掉,会影响map的size,解决方法一样在这里插入图片描述
反注册相当于从map里把kv对去掉,会影响map的size,解决方法一样,
临时生成容器,里面记录你想要清除的东西

在这里插入图片描述
现在就把多线程版本改成了IO多路复用版本(在linux优先使用EPOLL,效率很高)
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
想要监听写事件,send其实也是阻塞的,取决于缓冲区满不满,满了就阻塞了在这里插入图片描述在这里插入图片描述
**conn有读写,写1read 写2,write,3就是read and write,‘|’现在是按位相或 **在这里插入图片描述
现在就是读写都处理,但是现在无法得知读就绪还是写就绪
在这里插入图片描述
最简单的方式就是把mask传入进来,mask是1读就绪,mask是2写就绪,mask是3读写同时就绪

如果是file.obj是self.sock,就是accept,如果不是都是conn创建除的新的socket,在这里插入图片描述
也可以判断成,key.data,如果是self.recv就做下处理,self.accept就做下处理,总之是要做区分

events可能别人accept就绪了,别人也链接进来了,正好conn读写同时进行,所以event里到底有谁不好判断,有可能这里面不止一项,但是只要select不阻塞,那么events里至少有一个被监控对象就绪
在这里插入图片描述
这个与完之后,只可能是1,或者2 ,因为其他全是0在这里插入图片描述
**在handle就需要判断究竟谁就绪,
if mask &位与 1,不能使用elif,因为既可能读就绪,也可能写就绪 **在这里插入图片描述
现在的send需要用写就绪的方式,缓冲区没满是可写的,能否读和写彻底分离,现在是读里直接调用写
在这里插入图片描述
解耦可以分离开,queue,每个socket给每个queue单独分配,原来是给send fileobj发数据,现在应该是给queue,
现在想为每个socket配queue

在这里插入图片描述
data并没有限制用什么对象
在这里插入图片描述
现在为每一个conn单独配queue在这里插入图片描述
传一个key对象,这个key对象就是conn在这里插入图片描述在这里插入图片描述
如果是读就绪,就会从缓冲区里拿出来,拿出来做过处理,就是send出去在这里插入图片描述
handle能进来,一定是conn的,才能把mask送进来
在这里插入图片描述
key.data【1】就是queue,用这个queque.empty,不为空,key.fileobj,send在这里插入图片描述
修改一下用is socket还是有点问题在这里插入图片描述
运行一下
在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述
反复打印加号说明,说明一直是就绪的
3代表,至少是写就绪了
在这里插入图片描述
写就绪一直会告诉select要不要写,对于群聊软件大部分是读多写少,才用读监听,写多读少才用写监听在这里插入图片描述在这里插入图片描述
就会一直在跑
在这里插入图片描述
conn没活干了就不监听了
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值