python全栈学习笔记(二十一)IO多路复用

IO多路复用和python没关系,是系统底层实现的,这三个方法是系统底层提供的,python是通过这三种方法来实现IO多路复用
注:windows里只支持select
select相当其余两个差些,而且select最多能监听1024个
最早出现的是select,接着有了poll(它是对select做了优化,poll对数量没限制的,但是底层是通过for循环的,效率有些低),再接着出现了epoll(这个再次做了优化,epoll的内部就不再做for循环了,它的底层用的是异步。之前两个是通过for循环找到有变化的对象,再告诉我们,而epoll是在内部实现的一个机制,就是把所有对象放在epoll内部,然后哪个对象有了变化就上报epoll)。
select和poll是主动去找对象一个个问,而epoll则是被动的接受对象监听到的信息。相比而言,epoll性能优越很多。
nginx内部就是结合socket和epoll来监听的
Python中有一个select模块,其中提供了:select、poll、epoll三个方法,分别调用系统的 select,poll,epoll 从而实现IO多路复用。
原生的socket只能接受一个连接,多的只能等待,后来有了socketserver实现了并发的功能
下面这种情况是错误的。
sk1就相当于一个文件描述符
这样的代码执行只有sk1,

下面这种方式可以同时监听多个文件描述符(句柄)
server端
其中inputs参数返回信息给r_list 参数 1 则表示在这里停顿一秒,如果这一秒没有client连接上来,就继续执行接下来的代码

其中,下面这个第一个参数表示client连接上了返回正确信息,第三个表示client连接错了,返回错误的对象
通过这个功能,我们可以及时把错误的对象给踢出去

第二个参数传了什么值,会原封不动的传给w_list
这个就是select方法给我们提供的功能

client端


下面讲解下这个流程:
1、server端创建的socket对象,只能用来接收用户的连接,不能用来收发数据。
2、server端通过accetp(阻塞)来获取一个conn连接对象。
3、server端是通过conn对象来和client端收recv发send数据的


1、对于服务端的sk1来说,如果有人第一次来连接,它就会发生变化,然后就会被select。select的检测到,并返回值
2、
通过下面这种做法,就可以模拟出一个服务端同时和多个client通信,但本质是用for循环来查找的。
server端:
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket import select sk1 = socket.socket() ip_port = ("127.0.0.1",9999) sk1.bind(ip_port) sk1.listen() inputs = [sk1,] while True: r_list,w_list,e_list = select.select(inputs,[],inputs,1) print("目前有多少个人在连接%d" % len(inputs)) print(sk1) #如果有多个client连接过来,则inputs=[sk1,client1,client2,...] #虽然同时有多个对象,但是只有一个socket对象,所以select一次只能检测sk1, for sk in r_list: #有新的clent过来连接,socket对象就会变好,就会被select检测到,把sk1写进inputs里面,这里是sk1 if sk == sk1: conn,address = sk.accept() #如果client连接后再发数据,server可以通过accept接受到clent的数据,并创建连接对象conn,之后server和clent的收发数据就通过conn这个对象。 inputs.append(conn) else: data_byte = sk.recv(1024) data_str = str(data_byte,encoding="utf-8") sk.send(bytes(data_str+"你好",encoding="utf-8"))
client端:
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket,os obj = socket.socket() ip_port = ("127.0.0.1",9999) obj.connect(ip_port) while True: info = input(">>>>>>>> ") obj.sendall(bytes(info,encoding="utf-8")) ret = obj.recv(1024) print(str(ret,encoding="utf-8"))
我们要做到,client发送的消息,r_list只是读,写在w_list ,错误信息在e_list






线程就相当于多个人同时一起做


浙公网安备 33010602011771号