IO模型 :
模型即套路,是解决某个固定问题的方式方法
IO模型是解决IO问题的方式方法
IO指的是输入输出,输入输出设备的速度对比
CPU而言是非常慢的,例如:recv,input等
都是IO操作,IO操作最大的问题就是阻塞程序执行
IO模型要解决的也仅仅是网络相关的IO操作
IO模型有以下几个:
1.阻塞IO
2.非阻塞IO
3.IO多路复用(*****)
4.异步IO(会在爬虫阶段讲)
5.信号驱动(了解)
阻塞IO:
socket模块默认就是阻塞多的,同一时间
只能服务一个客户端
方法1:多线程
(好处:如果并发量不高的话,效率是比较高的,因为
每一个客户端都有单独的线程来处理)
(弊端:不可能无限的开线程,线程也需要占用资源)
方法2:多进程:
(优点:可以多个CPU并行处理)
(弊端:占用资源非常大,一旦客户端稍微多一点,立马就慢了)
方法3:线程池
(优点:保证了服务器正常稳定运行,管理线程的创建与销毁,
还负责创建和销毁线程,以及任务分配)
(弊端:一旦并发量超出了最大线程数量,就只能等前面的运行完毕)
真正导致效率低的是阻塞问题,但是上述方法,并没有真正解决问题,仅仅是
避开了阻塞问题.
方法4:协程
基于单线程并发
(优点,并不需要创建一堆线程,也不需要在线程间做切换,没有数量限制)
(弊端,不能利用多核优势,单核处理器,性能
是有上限的,如果真的并发量特别大.那么处理速度会变慢)
非阻塞IO:
即遇到IO操作也不导致程序阻塞,会继续执行
意味着即使遇到IO操作CPU执行权也不会被剥夺
程序效率就变高了
socket.setblocking()设置socket是否阻塞,默认为True
迭代过程中不允许修改元素内容
删除过程中 解释器不知道你删除了元素
多路复用:用一个线程来并发处理所有的客户端
使用select模块 只有一个函数:select
select需要三个函数:
1 r_list 需要被select检测可读状态的客户端 把所有socket放到该列表中,
select负责从中找出可以读取数据的客户端
2 w_list 需要被select检测可写状态的客户端 把所有socket放到该列表中,
select负责从中找出可以写入数据的客户端
3 x_list 存储要检测的异常条件
返回值是一个元组:包含三个列表:
readables 已经处于可读状态的socket 即数据已经到达缓冲区
writeables 已经处于可写状态的socket 即缓冲区没满 可以发送数据
x_list 忽略
在多路复用模型中,要先问select,哪些socket已经准备就绪 然后再处理这些已经就绪的socket
已经就绪的执行recv或者send 就不会在阻塞
在多路复用中,一旦select交给你一个socket,一定意味着,该socket已经准备就绪
可读或是可写
可读:recv recvfrom
可写:send sendto