一.先讲一个形象比喻五种io模型

1.阻塞I/O模型

老李去火车站买票,排队三天买到一张退票。

耗费:在火车站吃喝拉撒3天,其他事一件没干。

2.非阻塞I/O模型

老李去火车站买票,隔12小时去火车站文有没有退票,三天后买到一张票。

耗费:往返车站6次,路上6小时,其他时间做了好多事。

3.I/O

1)select/poll

老李去火车站买票,委托黄牛,(select黄牛一次只能帮1024个人买票,poll黄牛无上限)然后每隔离6小时打电话黄牛询问,黄牛三天内买到票,然后老李去火车站交钱领票。

耗费:往返车站2次,路上2小时,黄牛手续费100,打电话17次

2)epoll

老李去火车站买票,委托黄牛,黄牛买到后即通知老李去领,然后老李去火车站交钱领票。

耗费:往返车站两次,路上2小时,黄牛手续费100元,无需打电话。

4)信号驱动I/O模型

老李去火车站买票,给售票员留下电话,有票后,售票员电话通知老李,然后老李去火车站交钱领票。

耗费:往返车站2次,路上2小时,免费黄牛100元,无需打电话。

5)异步I/O模型

老李去火车站买票,给售票员留下电话,有票后,售票员电话通知老李并快递送票上门。

耗费:往返车站1次,路上一小时,免黄牛费100,无需打电话。

二.waitdata 和 copydata

1)等待数据准备 (Waiting for the data to be ready)
2)将数据从内核拷贝到进程中(Copying the data from the kernel to the process)

记住这两点很重要,因为这些IO模型的区别就是在两个阶段上各有不同的情况。

补充

#1、输入操作:read、readv、recv、recvfrom、recvmsg共5个函数,如果会阻塞状态,则会经理wait data和copy data两个阶段,如果设置为非阻塞则在wait 不到data时抛出异常

#2、输出操作:write、writev、send、sendto、sendmsg共5个函数,在发送缓存区满了会阻塞在原地,如果设置为非阻塞,则会抛出异常

#3、接收外来链接:accept,与输入操作类似

#4、发起外出链接:connect,与输出操作类似

三.阻塞IO模型
#服务端
from concurrent.futures import ThreadPoolExecutor
import socket server = socket.socket()
#重用端口
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) server.bind(("127.0.0.1",9999)) server.listen(5) #线程池
pool=ThreadPoolExecutor(3) def data_handler(conn):
print("一个新连接...")
while True:
data = conn.recv(1024)
conn.send(data.upper()) while True:
conn,addr = server.accept()
#切到处理数据的任务去执行
pool.submit(data_handler,conn) #客户端
import socket
c = socket.socket() c.connect(("127.0.0.1",9999)) while True:
msg = input(">>>:")
if not msg:continue
c.send(msg.encode("utf-8"))
data = c.recv(1024)
print(data.decode("utf-8"))

四.非阻塞IO模型

    在非阻塞IO中 需要不断循环询问操作是否有需要处理的数据

    这一来 对应程序而言 效率确实高

    但是操作系统而言 你的程序就像一个病毒 CPU江被你强行霸占

    当你的TCP程序 没有锁 没有数据接收 没有数据发送时 就是在做无用循环 浪费系统资源

#服务器
from concurrent.futures import ThreadPoolExecutor
import socket server = socket.socket()
#重用端口
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) server.bind(("192.168.11.96",9998)) server.listen(5) #设置是否为阻塞 默认阻塞
server.setblocking(False) def data_handler(conn):
print("一个新连接..")
while True:
data = conn.recv(1024)
conn.send(data.upper())
#已经连接的客户端
clients = []
# 需要发送的数据
send_datas=[]
#已经发送完的 需要删除的数据
del_datas = []
# 待关闭的客户端
closed_cs = []
import time
while True:
try:
conn,addr = server.accept()
#切到处理数据的任务去执行
#代码走到这里才算是连接成功
#把连接成功的客户端存起来
clients.append(conn)
except BlockingIOError:
# print("没有可以处理的连接 就干别的活儿")
#要处理的是已经连接成功的客户端
# 接受数据
for c in clients:
try:
data = c.recv(1024)
if not data:
#对方关闭了连接
c.close()
#从客户端列表中删除它
closed_cs.append(c)
continue
print("收到%s"%data.decode("utf-8"))
#现在非阻塞 send直接往缓存塞 如果缓存满了 肯定有错误 需要单独处理
#c.send(data.upper())
send_datas.append((c,data))
except BlockingIOError:
pass
except ConnectionRefusedError:
# 对方关闭了连接
c.close()
#从客户端iebook中删除它
closed_cs.append(c)
#处理发送数据
for data in send_datas:
try:
data[0].send(data[1].upper())
#发送成功需要删除 不能直接删除
# send_datas.remove(data)
del_datas.append(data)
except BlockingIOError:
continue
except ConnectionRefusedError:
# 客户端连接需要删除
data[0].close()
closed_cs.append(data[0])
#等待发送的数据需要删除
del_datas.append(data)
# 删除无用数据
for d in del_datas:
# 从待发送的列表中删除
send_datas.remove(d)
del_datas.clear()
for c in closed_cs:
clients.remove(c)
closed_cs.clear() #客户端 from concurrent.futures import ThreadPoolExecutor
import socket server = socket.socket()
#重用端口
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) server.bind(("192.168.11.96",9998)) server.listen(5) #设置是否为阻塞 默认阻塞
server.setblocking(False) def data_handler(conn):
print("一个新连接..")
while True:
data = conn.recv(1024)
conn.send(data.upper())
#已经连接的客户端
clients = []
# 需要发送的数据
send_datas=[]
#已经发送完的 需要删除的数据
del_datas = []
# 待关闭的客户端
closed_cs = []
import time
while True:
try:
conn,addr = server.accept()
#切到处理数据的任务去执行
#代码走到这里才算是连接成功
#把连接成功的客户端存起来
clients.append(conn)
except BlockingIOError:
# print("没有可以处理的连接 就干别的活儿")
#要处理的是已经连接成功的客户端
# 接受数据
for c in clients:
try:
data = c.recv(1024)
if not data:
#对方关闭了连接
c.close()
#从客户端列表中删除它
closed_cs.append(c)
continue
print("收到%s"%data.decode("utf-8"))
#现在非阻塞 send直接往缓存塞 如果缓存满了 肯定有错误 需要单独处理
#c.send(data.upper())
send_datas.append((c,data))
except BlockingIOError:
pass
except ConnectionRefusedError:
# 对方关闭了连接
c.close()
#从客户端iebook中删除它
closed_cs.append(c)
#处理发送数据
for data in send_datas:
try:
data[0].send(data[1].upper())
#发送成功需要删除 不能直接删除
# send_datas.remove(data)
del_datas.append(data)
except BlockingIOError:
continue
except ConnectionRefusedError:
# 客户端连接需要删除
data[0].close()
closed_cs.append(data[0])
#等待发送的数据需要删除
del_datas.append(data)
# 删除无用数据
for d in del_datas:
# 从待发送的列表中删除
send_datas.remove(d)
del_datas.clear()
for c in closed_cs:
clients.remove(c)
closed_cs.clear()

五.异步IO模型

import asyncio
asyncio.coroutine()
from concurrent.futures import ThreadPoolExecutor def task():
print("read start")
with open(r"D:\python视频存放目录\上海python全栈4期\day40\多路复用,降低CPU占用\服务器.py",encoding="utf-8") as f:
text = f.read()
# f.write()
print("read end")
return text def fin(f):
print("fin")
print(f.result()) pool = ThreadPoolExecutor(1)
future = pool.submit(task)
future.add_done_callback(fin) print("主 over")
# 这种方式看起来像是异步IO 但是对于子线程而言不是
# 在子线程中 执行read 是阻塞的 以为CPU必须切走 但是不能保证切到当前程序的其他线程
# 想要的效果就是 在执行read 是不阻塞 还能干其他活 谁能实现 只有协程
# asyncio 内部是使用的是协程

六.IO模型比较分析

第四十天 并发编程之io模型的更多相关文章

  1. python并发编程之IO模型 (四十九)

    IO模型介绍 http://www.cnblogs.com/linhaifeng/articles/7454717.html

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

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

  3. Python并发编程之IO模型

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

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

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

  5. 并发编程之IO模型

    一.阻塞IO(blocking IO) from concurrent.futures import ThreadPoolExecutor import socket server = socket. ...

  6. Python之旅:并发编程之IO模型

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

  7. python全栈开发从入门到放弃之socket并发编程之IO模型

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

  8. 并发编程之IO模型比较和Selectors模块

    主要内容: 一.IO模型比较分析 二.selectors模块 1️⃣ IO模型比较分析 1.前情回顾: 上一小节中,我们已经分别介绍过了IO模型的四个模块,那么我想大多数都会和我一样好奇, 阻塞IO和 ...

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

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

随机推荐

  1. 极其好用好学的规则引擎 - A2D规则引擎

    写了个简单的规则引擎,普通情况够用了: 比如2家公司有各自的利率计算规则,如下: 在C#方面,没有写在C#的业务逻辑代码中,而是移到了外部规则文件中,如(ACompanyRatePolicy.r): ...

  2. 朱晔和你聊Spring系列S1E4:灵活但不算好用的Spring MVC

    阅读PDF版本 本文会以一些例子来展现Spring MVC的常见功能和一些扩展点,然后我们来讨论一下Spring MVC好用不好用. 使用SpringBoot快速开始 基于之前的parent模块,我们 ...

  3. 在Linux的Windows子系统上(WSL)使用Docker(Ubuntu)

    背景 平时开发大部人都是在提供了高效GUI的window下工作,但是真正部署环境普遍都是在Linux中,所以为了让开发环境和部署环境统一,我们需要在windows模拟LInux环境,以前我们可能通过虚 ...

  4. Python-正则表达式总结版

    前言: 总是写不好正则表达式,时间长不用就有些忘记了,故此在总结一篇文章以便日后查阅. 一.常用的匹配规则总结表 模式 描述 \w 匹配字母数字及下划线 \W 匹配非字母数字及下划线 \s 匹配任意空 ...

  5. 【转载】KETTLE集群搭建

    一.集群的原理与优缺点 1.1集群的原理 Kettle集群是由一个主carte服务器和多个从carte服务器组成的,类似于master-slave结构,不同的是’master’处理具体任务,只负责任务 ...

  6. 【转载】SQL中inner join、outer join和cross join的区别

    对于SQL中inner join.outer join和cross join的区别很多人不知道,我也是别人问起,才查找资料看了下,跟自己之前的认识差不多, 如果你使用join连表,缺陷的情况下是inn ...

  7. Python Revisited Day 03 (组合数据类型)

    目录 第三章 组合数据类型 3.1 序列类型 3.1.1 元组 3.1.2 命名的元组 (collections.nametuple()) 3.1.3 列表 (查询有关函数点这) 3.1.4 列表内涵 ...

  8. D - Nature Reserve(cf514,div2)

    题意:给出n(n<=1e5)个点,求一个最小的圆,与x轴相切,并且包含这n个点 思路:我第一想到的是,这个圆一定会经过一个点,再根据与x轴相切,我们可以找到最小的圆,让它包含其余的点,但是如何判 ...

  9. UITableView加载数据,没有数据,没有网络界面处理

    https://blog.csdn.net/chmod_r_755/article/details/53231461 俗话说的好,傻逼的APP都是相似的,牛逼的APP各有各的牛逼...但是UITabl ...

  10. BAT (中国互联网公司三巨头)

    BAT,B=百度.A=阿里巴巴.T=腾讯,是中国互联网公司百度公司(Baidu).阿里巴巴集团(Alibaba).腾讯公司(Tencent)三大互联网公司首字母的缩写.百度总部在北京.阿里巴巴总部在浙 ...