1.网络IO的两个阶段 waitdata copydata
send 先经历:copydata阶段
recv 先经历:waitdata阶段 再经历 copydata阶段 2.阻塞的IO模型
之前写的都是阻塞 无论多线程 多进程 还是进程池 线程池 3.非阻塞IO模型
非阻塞:最直接的体现 所有和读写相关的函数 都不会阻塞
意味着 在读写的时候 并不能确定目前是否可以读写 一旦不能读写就派出异常
只能使用try except 看是否可以读写
在非阻塞io中 需要不断循环询问操作是否需要处理的数据
这样一来 对应程序而言 效率确实高了
但是操作系统而言 你的程序就像一个病毒 一直强行占用cpu
当你的TCP程序 没有连接 没有数据接受 没有数据发送时 就是在做无用循环 浪费系统资源 4.多路复用 待改:有中间select recv等待结果
核心函数select
帮你检测所有的连接 找出可以被处理(可以读写)的连接
作为处理数据的一方 不再需要重复去向系统询问 select给你谁,你就用谁来处理 举例待改 举例1:迭代期间不能修改被迭代的对象
# li = [1,2,3,4,5,6]
# def mytlist_iter():
# for i in range(len(li)):
# yield li[i]
# for j in mytlist_iter():
# if j == 5:
# li.remove(5)
# d = {"a":1,"b":2}
# for k in d:
# if k == "a":
# d.pop(k) 举例2:(多路复用)
服务端:
from concurrent.futures import ThreadPoolExecutor
import socket server = socket.socket()
# 重用端口
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) server.bind(("192.168.11.210",9999)) 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 = []
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 ConnectionResetError:
# 对方关闭了连接
c.close()
# 从客户端列表中删除它
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 ConnectionResetError:
# 客户端连接需要删除
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() 客户端:
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模型
2.非阻塞IO模型
协程是一种非阻塞IO
1.setblocking(False)将阻塞修改非阻塞
2.一旦是非阻塞 在执行accept recv send 就会立马尝试读写数据 一旦数据没有准备
好就抛出异常
3.捕获异常
4.如果没有异常说明数据准备好了 直接处理
5.捕获到异常 那就做别的事情
可以实现单线程并发的效果 会大量占用CPU资源 3.多路复用
将所有连接家给select来管理 管什么? 管哪个连接可以被及处理
作为处理任务的乙方事情变少了 不需要重复不断的问操作系拿数据 而是等待select返回需要处
理的连接
等待则意味着select是阻塞的 3.1 创建连接和管理连接
1.创建服务器socket对象
2.将服务器对象交给select来管理
3.一旦有客户端发起连接 select将不在阻塞
4.select将返回一个可读的socket对象(第一次只有服务器)
5.服务器的可读代表有连接请求 需要执行accept 返回一个客户端连接conn 由于是非阻塞 不能立
即去recv
6.把客户端socket对象也交给select来管理 将conn加入两个被检测的列表中
7.下一次检测到可读的socket可能是服务器 也可能是客户端 所以加上判断 服务器就accept 客户端
就revc
8.如果检测到有可写(可以send就是系统缓存可用)的socket对象 则说明可以向客户端发送数据了
7 and 8 的执行顺序是不固定的 3.2 处理数据收发
两个需要捕获异常的地方
1.recv 执行第七步 表示可以读 为什么异常 只有一种可能是客户端断开连接
还需要加上 if not 判断是否有数据 linux下 对方下线不会抛出异常 会收到空消息
2.send 执行第八步 表示可以写 为什么异常 只有一种可能客户端断开连接 异步IO 不仅仅指网络IO 也包括本地IO
非阻塞IO 和多路复用 解决的都是网络IO的阻塞问题
本地IO 可以通过子线程 或子进程 来避免阻塞 但是对子线程或者子进程而言 依旧会阻塞 最终的解决方案就是协程 asyncio 该模块实现异步IO 内部使用协程实现

多路复用 阻塞/非阻塞IO模型 网络IO两个阶段的更多相关文章

  1. IO模型介绍 以及同步异步阻塞非阻塞的区别

      阻塞:用户进程访问数据时,如果未完成IO,等待IO操作完成或者进行系统调用来判断IO是否完成非阻塞:用户进程访问数据时,会马上返回一个状态值,无论是否完成 同步:用户进程发起IO(就绪判断)后,轮 ...

  2. 并发编程 - IO模型 - 1.io模型/2.阻塞io/3.非阻塞io/4.多路复用io

    1.io模型提交任务得方式: 同步:提交完任务,等结果,执行下一个任务 异步:提交完,接着执行,异步 + 回调 异步不等结果,提交完任务,任务执行完后,会自动触发回调函数同步不等于阻塞: 阻塞:遇到i ...

  3. python开发IO模型:阻塞&非阻塞&异步IO&多路复用&selectors

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

  4. [翻译]各个类型的IO - 阻塞, 非阻塞,多路复用和异步

    同事推荐,感觉写的不错就试着翻译了下. 原文链接: https://www.rubberducking.com/2018/05/the-various-kinds-of-io-blocking-non ...

  5. linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)

      IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file ...

  6. (转)同步异步,阻塞非阻塞 和nginx的IO模型

    同步异步,阻塞非阻塞 和nginx的IO模型  原文:https://www.cnblogs.com/wxl-dede/p/5134636.html 同步与异步 同步和异步关注的是消息通信机制 (sy ...

  7. Linux IO模型(同步异步阻塞非阻塞等)的几篇好文章

    聊聊同步.异步.阻塞与非阻塞聊聊Linux 五种IO模型聊聊IO多路复用之select.poll.epoll详解 ​

  8. 理解同步,异步,阻塞,非阻塞,多路复用,事件驱动IO

    以下是IO的一个基本过程 先理解一下用户空间和内核空间,系统为了保护内核数据,会将寻址空间分为用户空间和内核空间,32位机器为例,高1G字节作为内核空间,低3G字节作为用户空间.当用户程序读取数据的时 ...

  9. python并发编程之IO模型 同步 异步 阻塞 非阻塞

    IO浅谈 首先 我们在谈及IO模型的时候,就必须要引入一个“操作系统”级别的调度者-系统内核(kernel),而阻塞非阻塞是跟进程/线程严密相关的,而进程/线程又是依赖于操作系统存在的,所以自然不能脱 ...

随机推荐

  1. 关于js原型链

    关于原型链,我们先贴上一张图(来自某知乎大佬专栏),然后听我娓娓道来. 先来说说什么是原型? JavaScript 中的对象有一个特殊的 [[Prototype]] 内置属性,其实就是对于其他对象的引 ...

  2. windows下进程间通信与线程间通信

    进程间通信: 1.文件映射(Memory-Mapped Files) 文件映射(Memory-Mapped Files)能使进程把文件内容当作进程地址区间一块内存那样来对待.因此,进程不必使用文件I/ ...

  3. oracle 创建自定义的流水号

    ; --你确定流水号只要3位? 使用它的下一个值用: seq_abc_taskid.nextval查询当前值用:seq_abc_taskid.currval比如你现在要插入一行到abc,你可以 ,se ...

  4. 绘图之EasyUI+Highcharts+Django

    前言: 在web开发过程中经常会出现图表展示数据的业务需求,如何把数据通过图表的形式,展示在页面上呢?本文将结合EasyUI.Highcharts.Django做一个简单的图表展示web应用: 一.E ...

  5. vue数组操作不更新视图问题

    vue 观察数组的变异方法 更新视图 push() pop() shift() unshift() splice(i,n,arr) sort(xx) reverse() ex: app.book.pu ...

  6. struts项目部署在Tomca上在断网情况下启动报错

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6015693.html 前段时间,项目部署到现场后,反馈Tomcat能正常启动,但是项目有时访问不了也不报错. ...

  7. 使用javassist进行动态编程

    今天在研究dubbo时,发现一个新的知识点,可以使用javassist包进行动态编程,hibernate也使用该包进行编程.晚上百度了很多资料,将它的特性以代码的形式展现出来. package com ...

  8. matlab 调试日志

    debug=; diary off if debug delete('log.txt'); !del log.txt diary('log.txt'); diary ON end diary OFF

  9. windows 文件/文件夹操作

    move命令 命令作用:移动某个文件到指定的文件夹下 将D:\file\abc.zip 移动到 E:\test\文件夹下 move d:\file\abc.zip e:\test\ 移动之后再原来的文 ...

  10. nodejs项目文件搭建环境

    nodeJS,作为一门较为“新鲜的”的原因,近年来普遍受到一些前端想转为全栈的ITer青睐,在想用nodeJS配合数据库开发出一个小玩意的路上,萌新们第一步便要遇到就是环境的支持.node作为Java ...