IO模型

匿名 (未验证) 提交于 2019-12-02 23:05:13

什么是IO模型?

IO指的是输入输出,其执行速度非常慢

模型,只固定的套路

IO模型就是指实现输入输出的套路

IO的分类

1.本地IO 指的是输入输出到本地计算机 如:写入硬盘

2.网络IO 指的是输入输出到网络中的计算机,速度远比本地IO慢

网络IO输入输出过程

IO模型的分类(重点)

1.阻塞型IO

  之前学习的IO操作除了gevent都是阻塞型的

  1.可以利用多线程来提高IO

    线程不能太多,会造成内存溢出

  2.线程池可以解决下线程太多问题

    但如果线程池达到最大数,其他客户端将进入等待

  3.在单线程下并发来处理 可以使单核下的效率最高

2.非阻塞IO

非阻塞IO的服务器

import socket server = socket.socket() server.bind(('192.168.1.67',4396)) server.listen() #设置为非阻塞IO server.setblocking(False) #存放所有连接过来的客户端 clients = [] while True:     try:         client,addr = server.accept()         print('连入了一个客户端!')         clients.append(client)     except BlockingIOError:          #已经关闭的客户端         close_c = []         #将要回复的客户端以及数据         msg_ls = []         #接受数据循环         for c in clients:             try:                 data = c.recv(1024)                 if not data:                     c.close()                     close_c.append(c)                 #不能直接发,因为操作系统缓存满了会抛出异常                 msg_ls.append((c,data))             except BlockingIOError:                 pass             except ConnectionResetError:                 c.close()                 close_c.append(c)          #发送数据的循环         #保存已发送的客户端和数据         rm_msg = []         for client_and_data in msg_ls:             client = client_and_data[0]             data = client_and_data[1]             try:                 client.send(data.upper())                 #加入删除列表                 rm_msg.append(client_and_data)             except BlockingIOError:                 pass                  #从将要回复的客户端和数据列表删除已经发送的成功客户端和数据         for i in rm_msg:             msg_ls.remove(i)         #清空已经发送完成的客户端和数据列表         rm_msg.clear()                  #从连入的客户端列表删除已经关闭的客户端列表         for c in close_c:             clients.remove(c)         #清空已经关闭的客户端列表         close_c.clear() 

非阻塞IO客户端

import socket import os,time client = socket.socket() client.connect(('192.168.1.67',4396)) while True:     msg = 'hello i am:%s'%os.getpid()     time.sleep(1)     if not msg:         continue     client.send(msg.encode('utf-8'))     data = client.recv(1024)     print(data.decode('utf-8')) 

3.多路复用

非阻塞IO对CPU占有率太高,为了解决这一问题我们使用多路复用

什么是多路复用?

多个连接复用一个线程 反过来说就是一个线程处理多个连接 提高了单线程的处理能力

多路复用提高的是单线程处理网络IO的效率

协程提升的是单线程处理所有IO的效率

多路复用服务器:

import socket,select server = socket.socket() server.bind(('192.168.1.67',4396)) server.listen() #select 是帮我们监控连接 #需要给他传两个参数列表,一个检测是否可读(是否可以执行recv),一个检测是否可写(是否执行send) rlist = [server,] wlist = [] #默认select是阻塞的.直到其中有一个或几个需要被处理 #存储要发送的数据 msg = {}  #返回值: #1.可读的连接(可以执行recv) #2.可写的连接(可以执行send) while True:     readable_list,writeable_list,_ = select.select(rlist,wlist,[])     #接下来处理可读可写的列表      #处理可读的列表     for c in readable_list:         if c == server:#说明当要被处理的是服务器             client,addr = server.accept()             #把客户端交给select来检测是否可读             rlist.append(client)         else:             print('客户端可以recv了!')             data = c.recv(1024)             print(data.decode('utf-8'))             #将客户端也交给select来检测是否可写             wlist.append(c)             msg[c] = data      #处理可写列表     for w in writeable_list:         w.send(msg[w].upper())         #将已经发送完成的连接从检测列表删除         wlist.remove(w) 

多路复用客户端:

import socket,os,time client = socket.socket() client.connect(('192.168.1.67',4396)) while True:     msg = 'hello i am:%s'%os.getpid()     time.sleep(1)     if not msg:         continue     client.send(msg.encode('utf-8'))     print(client.recv(1024).decode('utf-8')) 

4.异步IO

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!