IO模型

一、IO模型

IO模型就是解决IO问题的方式

IO指的是输入输出,输入输出设备的速度与CPU相比来说是非常慢的,比如recv,input等都是IO操作

IO操作的最大问题就是会阻塞程序执行

IO模型要解决的仅仅是网络IO操作

IO模型分类(5类):

1、阻塞IO

socket默认模块就是阻塞的

问题:同一时间只能服务一个客户端

解决方法一:多线程(优点:若并发量不高,效率是比较高的,因为每个客户端都有单独线程来处理。弊端:线程需要占用资源,不能无限去开线程)

解决方法二:多进程(优点:可以多个CPU并行处理。弊端:占用的资源非常大,一旦客户很多,速度就会变慢)

解决方法三:线程池(优点:保证了服务器正常运行,负责创建和销毁线程以及任务分配。弊端:并发量超出最大线程数量,会造成阻塞)

解决方法四:协程(优点:不需要创建线程,不需要再线程之间切换,没有数量限制。弊端:不能利用多核优势,单核处理器性能是有上限的,如果并发很大处理器速度就会变慢)

真正导致效率低的是阻塞问题,以上方法都没有真正的解决阻塞问题,只是避开了阻塞问题

2、非阻塞IO

遇到IO操作也不会阻塞,仍然会继续执行。即使遇到IO,CPU执行权也不会剥夺,程序效率会变更高。

3、IO多路复用*****

一些程序占用CPU太高,原因是需要无限的循环去向操作系统拿数据

IO多路复用也是单线程并发处理所有请求

与非阻塞不同之处是不需要频繁不断地发送系统调用,只要等到select选择准备就绪socket,然后进行处理

4、异步IO(爬虫阶段)

5、信号驱动(了解)

二、IO多路复用

 1 import socket
 2 c = socket.socket()
 3 c.connect(("127.0.0.1,8080))
 4 print("已连接")
 5 
 6 while True:
 7     msg = input(">>>").strip()
 8     if not msg:continue
 9     c.send(msg.encode("utf-8"))
10 
11     data = c.recv(1024)
12     print(data.decode("utf-8"))
客户端 View Code
 1 import socket
 2 import time
 3 import select
 4 s = socket.socket()
 5 s.bind(("127.0.0.1",8080))
 6 s.listen()
 7 
 8 r_list = [s]
 9 w_list = []
10 data_dic ={}
11 while True:
12     readables,writeables,_ = select.select(r_list,w_list,[])
13     for i in readables:
14         if i ==s:
15             c,_ = i.accept()
16             r_list.append(c)
17         else:
18             try:
19                 data = i.recv(1024)
20                 if not data:
21                     i.close()
22                     r_list.remove(i)
23                     continue
24                 print(data)
25                 w_list.append(i)
26                 data_dic[i] =data
27             except ConnectionResetError:
28                 i.close()
29                 r_list.remove(i)
30     for i in writeables:
31         try:
32             i.send(data_dic[i].upper())
33         except ConnectionResetError:
34             i.close()
35         finally:
36             data_dic.pop(i)
37             w_list.remove(i)
服务器 View Code

三、阻塞IO模型

 1 import socket
 2 import os
 3 c = socket.socket()
 4 c.connect(("127.0.0.1",9999))
 5 print("connect...")
 6 
 7 while True:
 8     msg = "%s 发来问候"% os.getpid()
 9     if not msg:continue
10     c.send(msg.encode("utf-8"))
11     data = c.recv(1024)
12     print(data.decode("utf-8"))
客户端 View Code
 1 import socket
 2 from threading import Thread
 3 s = socket.socket()
 4 s.bind(("127.0.0.1",9999))
 5 s.listen
 6 
 7 def talking(c):
 8     while True:
 9         try:
10             data = c.recv(1024)
11             print("recv...")
12             if not data:
13                 c.close()
14                 break
15             c.send(data.upper())
16         except ConnectionResetError:
17             c.close()
18             break
19 while True:
20     c,addr = s.accept()
21     print("accept...")
22     t = Thread(target=talking,args=(c,))
23     t.start()
服务器 View Code

四、非阻塞IO模型

 1 import socket
 2 c = socket.socket()
 3 c.connect(("127.0.0.1",9999))
 4 print("已连接")
 5 
 6 while True:
 7     msg = input(">>>").strip()
 8     if not msg:continue
 9     c.send(msg.encode("utf-8"))
10     data = c.recv(1024)
11     print(data.encode("utf-8"))
客户端 View Code
 1 import socket
 2 s = socket.socket()
 3 s.bind(("127.0.0.1",9999))
 4 s.listen()
 5 s.setblocking(False)
 6 
 7 cs = []
 8 send_cs = []
 9 
10 while True:
11     try:
12         c,addr = s.accept()
13         print("run accept")
14         cs.append(c)
15     except BlockingIOError:
16         for c in cs[:]:
17             try:
18                 data = c.recv(1024)
19                 if not data:
20                     c.close()
21                     cs.remove(c)
22                 print(data.decode("utf-8"))
23                 send_cs.append((c,data))
24             except BlockingIOError:
25                 continue
26             except ConnectionResetError:
27                 c.close()
28                 cs.remove(c)
29         for item in send_cs[:]:
30             c,data = item
31             try:
32                 c.send(data.upper())
33                 send_cs.remove(item)
34             except BlockingIOError:
35                 c.close
36             except ConnectionResetError:
37                 c.close()
38                 send_cs.remove(item)
39                 cs.remove(c)
服务器 View Code
原文地址:https://www.cnblogs.com/zhangzhechun/p/10518872.html