Python_IO模型
#IO模型 #同步IO 存在线程等待,就叫做同步IO #阻塞IO #Socket.accept() 用户态请求内核态,内核态等待客户端,用户态被挂起,进入阻塞状态,这种现象就叫做阻塞IO #非阻塞IO #socket.setblocking(false) 用户态请求内核态,内核态查看是否有客户端请求,当即向用户态返回结果,用户态接受结果,继续执行,不会被挂起,这种现象叫做非阻塞IO #IO多路复用 #模块: Windows Python: # 提供: select # Mac Python: # 提供: select # Linux Python: # 提供: select、poll、epoll #利用select等模块请求内核态,此时,用户态被挂起,内核态等待,直到有客户端请求,内核态返回结果,用户态执行accept(),将内核态的客户端连接复制到用户态, #多路复用实现了服务器并发的功能 #水平触发(select属于水平触发) #________--------_______ 下划线为0,横线为1,当执行到横线1这段时,会触发内核态返回,叫做水平触发 #边缘触发 #______ ------ ______ 当执行到下划线到横线之间的这段距离时,触发内核态返回,叫做边缘触发 #异步IO 线程0阻塞,叫做异步IO
#同步IO
#IO多路复用
#select模块
#select 模块 #采用select方式IO多路复用请求的模块,支持所有操作系统 #缺点:相对于epoll,效率不高 #使用 #s=select.select([sock,][][]) #创建select多路复用,sock是个socket对象,[socket,]是个列表对象,可以实现用户态向内核态请求多个等待对象,是实现IO并发的关键 # #导入select模块和socket模块 import select,socket #创建TCP socket sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #绑定 sock.bind(("127.0.0.1",8080)) #监听 sock.listen(5) print(sock) print("the server is start...") sock_tuple=[sock,] while 1: #创建select多路复用,等待sock_tuple列表里的所有对象, # 任意一个对象返回结果,内核态就会返回该对象, # select是通过循环访问实现的,epoll模块是通过自报家门的方式,可以直接获取到是哪个对象获取了信息, # 相对于select效率更高 s=select.select(sock_tuple,[],[])[0][0] #判断是否是服务器对象,有客户端请求访问 if s==sock: #从内核态获取客户端的连接到用户态 conn,add=s.accept() #将获取的新的客户端的连接,加入到多路复用请求内核态的对象列表中 sock_tuple.append(conn) else: try: #接收客户端的信息 data=s.recv(1024).decode("utf-8") #发送信息到客户端 s.send(data.upper().encode("utf-8")) except Exception as e: #出现异常,将客户端对象从内核态等待的对象列表中移除 sock_tuple.remove(s)
#selectors模块
#selectors #是一个根据操作系统,自动选择select,poll,epoll方式的IO多路复用的模块 #使用 #sel=selectors.DefaultSelector() 创建Selectors 对象 #sel.register(sock,selectors.EVENT_READ,acce) 注册一个IO多路复用的事件,如果sock对象,有人请求,就调用acce方法 #key,mask=sel.selector() #开始请求列表里的所有对象,到内核态,内核态获取到关于此对象的信息,返回到用户态,key(data,fileobj),mask #key.data 获取关于此对象请求成功的回调函数 key.fileobj 关于收到请求信息的对象 #调用关于此对象的回调函数 ket.data(key.fileobj,mask) #sel.unregister(sock) 取消sock对象的多路复用事件 import selectors,socket #内核态取回客户端请求连接到用户态的函数 def acce(sock,mask): conn,addr=sock.accept() conn.setblocking(False) #注册新的客户端连接到等待集合对象 sel.register(conn,selectors.EVENT_READ,talk) #连接读写的函数 def talk(conn,mask): try: data=conn.recv(1024).decode("utf-8") conn.sendall(data.encode("utf-8")) except Exception as e: sel.unregister(conn) #创建socket对象 sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #绑定 sock.bind(("127.0.0.1",8080)) #监听 sock.listen(5) #将socket设为非阻塞 sock.setblocking(False) #创建selectors对象 sel=selectors.DefaultSelector() #将sock注册为selectors的水平事件触发,回调函数为acce sel.register(sock,selectors.EVENT_READ,acce) print("the server is start..") while 1: #循环请求内核态关于注册的对象是否有程序请求,如果有程序请求该对象,该对象就会从内核态返回 events=sel.select() #获取从内核态返回的数据,包括data回调函数,fileob注册对象以及mask for key,mask in events: #获取关于此对象等待成功的回调函数 fun=key.data #执行该回调函数,参数为key.fileobj 触发该事件对象,mask参数 fun(key.fileobj,mask)
#异步IO
异步IO 0阻塞,没有等待
二十二.Python_IO模型
猜你喜欢
转载自blog.csdn.net/qq_39663113/article/details/85949246
今日推荐
周排行