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

 

 

 

 

 

 

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

 

posted @ 2016-07-25 17:11  爬行的龟  阅读(88)  评论(0)    收藏  举报
如有错误,欢迎指正 邮箱656521736@qq.com