IO模型

  解决IO问题的方式方法
  问题是:IO操作阻塞程序执行
  解决的也仅仅是网络IO操作
 
  一般数据传输经历的两个阶段,如图:

  IO阻塞模型分类:

  1. 阻塞IO
  2. 非阻塞IO
  3. 多路复用IO
  4. 异步IO(爬虫阶段)
  5. 信号驱动IO(了解)

1、阻塞IO模型

  socket模块默认是阻塞的,一个读操作流程如下:

  问题:

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

  解决办法:

    1. 多线程

      优点:如果并发量不高,效率是较高的,因为每个客户端都有单独线程来处理

      缺点:不可能无限的开启线程,线程也需要占用资源

    2. 多进程

      优点:可以多个CPU并行处理

      弊端:占用资源非常大,一旦客户端稍微多一点,立马就慢了

    3.线程池

      优点:保证了服务器正常运行,还帮你负责创建和销毁线程,以及任务分配

      缺点:一旦并发量超出最大线程量,就只能等签名的运行完毕。

    4. 协程

      优点:不需要创建一段线程,也不需要在线程间做切换,没有数量限制

      缺点:不能利用多核优势

    结果:真正倒是效率低的是阻塞问题,但上述办法并没有真正的解决阻塞问题。

2、非阻塞IO模型

  遇到IO操作也不阻塞,会继续执行。意味着即使遇到IO操作CPU执行权也不会被剥夺

  方法:设置socket使其变为non-blocking,即server.setblocking(False),具体流程如下:

  从图中看出,非阻塞的recv系统调用之后,进程没有被阻塞,操作系统立马把结果返回给进程,如果数据还没准备好,则抛出异常,进程可以去做其他的事,然后在发起recv系统调用,重复上述过程(这个过程通常被称为轮询),一直到数据准备好,再拷贝数据到进程进行数据处理。需要注意,拷贝数据的整个过程,进程仍然是属于阻塞状态。

  缺点: 占用CPU太多,原因是需要无限的循环去向操作系统拿数据。

import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('127.0.0.1', ))
server.listen()
server.setblocking(False)
# 所有客户端的socket
conns = []
# 所有需要返回数据的客户端
send_cs = [] while True:
try:
conn, client_addr = server.accept()
print(client_addr,'已连接')
conns.append(conn)
except BlockingIOError:
# 接收数据
for conn in conns[:]:# 和conns.copy()一样,原因:迭代过程不能删除元素
try:
data = conn.recv()
print(data)
send_cs.append((data, conn))
# send也是IO操作,在一些极端情况下,如系统缓存满了,肯定也会抛出异常
# 所以,send要单拿出来处理
except BlockingIOError:
continue
except ConnectionResetError:
conn.close()
conns.remove(conn)
# 发送数据
for item in send_cs[:]:
data, conn = item
try:
conn.send(data.upper())
# 如果发送成功就把数据从列表中删除
send_cs.remove(item)
except BlockingIOError: # 如果缓冲区满了 就下次再发
continue
except ConnectionResetError:
conn.close()
send_cs.remove(item)
conns.remove(conn)

服务端代码

3、多路复用IO

  用一个线程来处理并发所有的客户端。

  需要使用select模块,select原理:把所有的socket交给select,select会不断轮询所负责的所有socket,当某个socket有数据到达,就通知进程继续执行后面代码。

  流程:程序发起一个select调用,select使整个进程阻塞,直到有socket准备就绪,select就返回,这个时候进程在调用read操作,直接从缓冲中把数据拷贝到进程。流程图如下:

import socket
import select server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("127.0.0.1", ))
server.listen() r_list = [server] # 监测是否收到数据的客户端
w_list = [] # 监测是否需要发送数据的客户端
x_list = [] # 用来发送数据
data_dic = {} while True:
readables, writeables, _ = select.select(r_list, w_list, x_list)
# 接收数据以及建立连接
for conn in readables:
if conn == server:
new_conn, _ = conn.accept()
r_list.append(new_conn)
else:
try:
data = conn.recv()
if not data:
conn.close()
r_list.remove(conn)
continue
print(data)
# 发送数据
w_list.append(conn)
data_dic[conn] = data
except ConnectionResetError:
conn.close()
r_list.remove(conn)
# 发送数据
for conn in writeables:
try:
conn.send(data_dic[conn].upper())
except ConnectionResetError:
conn.close()
finally:
data_dic.pop(conn)
w_list.remove(conn)

服务端代码

import socket
import threading
from threading import Thread def communication():
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', ))
while True:
msg = "%s say hello for you"%threading.current_thread()
if not msg:
continue
client.send(msg.encode("utf-8"))
data = client.recv()
print(data.decode("utf-8")) for i in range():
Thread(target=communication).start()

客户端代码

  强调:select的优势在于可以处理多个连接,并不适用于单个连接

  优点:占用资源少,不消耗太多CPU,同时能够为多个客户端提供服务。(适用于简单的事件驱动服务器)

  缺点:需要消耗大量时间区轮询各个socket,更好的选择时epoll,其次把事件探测和响应夹杂在一起,耦合性增加

python并发编程之IO阻塞基础知识点的更多相关文章

  1. Python并发编程之IO模型

    目录 IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) IO多路复用 异步IO IO模型比较分析 selectors模块 一.IO模型介绍 Stevens ...

  2. python并发编程之IO模型,

    了解新知识之前需要知道的一些知识 同步(synchronous):一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行 #所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调 ...

  3. python并发编程之IO模型(Day38)

    一.IO模型介绍 为了更好的学习IO模型,可以先看同步,异步,阻塞,非阻塞 http://www.cnblogs.com/linhaifeng/articles/7430066.html#_label ...

  4. 33 python 并发编程之IO模型

    一 IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非 ...

  5. 五 python并发编程之IO模型

    一 IO模型介绍 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问 ...

  6. python并发编程之IO模型(实践篇)

    一.阻塞IO 介绍略(请看概念篇) 二.非阻塞IO 在非阻塞式IO中,用户进程需要不断的主动询问kernel数据准备好了没有 # 服务端 import socket import time serve ...

  7. 第十篇.6、python并发编程之IO模型

    一 IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非 ...

  8. 第 13 章 python并发编程之io模型

    一.IO模型介绍 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问 ...

  9. 38、python并发编程之IO模型

    目录: 一 IO模型介绍 二 阻塞IO(blocking IO) 三 非阻塞IO(non-blocking IO) 四 多路复用IO(IO multiplexing) 五 异步IO(Asynchron ...

随机推荐

  1. SpringBoot从零到上线

    SpringBoot精要 SpringBoot的四个核心 1.自动配置:针对很多Spring应用程序常见的应用功能,SpringBoot能自动提供相关配置. 在任何Spring应用程序的源代码中,都可 ...

  2. 使用visualStudio2017创建一个简单的控制台程序

    步骤: 1.  打开visual studio开发工具 2. 选择文件>新建>项目 如下图所示: 3. 选择window金典桌面>控制台应用程序 并填写好想项目名称和选择项目存储地址 ...

  3. .net core jwt 入门记录

    从百度里搜索里搜索了很多jwt的文章,跟着文章写了一个demo,这里记录下学习过程中碰上的问题.看文章多遍,不如手工实现一次. 模板已上传到github.com:dogvane/webapi_jwt_ ...

  4. [MySQL] MVCC 多版本并发控制实现的事务

    1.没有一个统一的实现标准,实现了非阻塞的读操作,写操作也只锁定必要的行2.通过保存数据在某个时间点的快照实现的3.典型的有乐观并发控制和悲观并发控制4.innodb的mvcc是每次事务都有递增的版本 ...

  5. 使用WordPress制作微信小程序

    0 产品由来 微信小程序具有即来即用.轻量化.与微信贴合性好的特点.对于独立产品来说,使用微信小程序能够较好的服务与个人及现在的互联网社群,提升用户体验. 本次设计的微信小程序是面向无人机开发者社区的 ...

  6. java.lang.IllegalArgumentException: Called attach on a child which is not detached: ViewHolder

    转载请标明出处,维权必究:https://www.cnblogs.com/tangZH/p/10116298.html 在项目过程中出现了上述错误. 会出现这样的错误是在我使用: notifyItem ...

  7. sqlserver安装报错:an error was encountered 数据无效

    解决方法:下载的包损坏,重新下载包

  8. jquery监听textarea内容变化

    $('#textarea').bind('input propertychange', function(){ var length = $("#textarea").val(). ...

  9. mongoDB概述

    mongoDB介绍 是一个开源的文档数据库,基于分布式文件存储的数据库.由 C++ 语言编写,并领先的 NoSQL 数据库(非关系型数据库)MongoDB 是由 c++语言编写. MongoDB 是一 ...

  10. P4013 数字梯形问题 网络流

    题目描述 给定一个由 nn 行数字组成的数字梯形如下图所示. 梯形的第一行有 mm 个数字.从梯形的顶部的 mm 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径. 分别 ...