IO模型,非阻塞IO模型,select实现多路复用
1. IO阻塞模型
IO问题:
输入输出
我要一个用户名用来执行登陆操作,问题用户名需要用户输入,输入需要耗时, 如果输入没有完成,后续逻辑无法继续,所以默认的处理方式就是 等
将当前进程阻塞住,切换至其他进程执行,等到按下回车键,拿到了一个用户名,再唤醒刚才的进程,将状态调整为就绪态
以上处理方案 就称之为阻塞IO模型
存在的问题:
当执行到recv时,如果对象并没有发送数据,程序阻塞了,无法执行其他任务
解决方案:
1.1 多线程或多进程
当客户端并发量非常大的时候,服务器可能就无法开启新的线程或进程,如果不对数量加以限制 服务器就崩溃了
1.2 线程池或进程池
首先限制了数量 保证服务器正常运行,但是问题是,如果客户端都处于阻塞状态,这些线程也阻塞了
1.3 协程
使用一个线程处理所有客户端,当一个客户端处于阻塞状态时可以切换至其他客户端任务
2.非阻塞IO模型
阻塞IO模型在执行recv 和 accept 时 都需要经历wait_data
非阻塞IO即 在执行recv 和accept时 不会阻塞 可以继续往下执行
如何使用:
将server的blocking设置为False 即设置非阻塞
存在的问题 :
这样一来 你的进程 效率 非常高 没有任何的阻塞
很多情况下 并没有数据需要处理,但是我们的进程也需要不停的询问操作系统 会导致CPU占用过高
而且是无意义的占用
案例:使用server
import socket
import time server = socket.socket()
server.bind(('192.168.13.29', 8080))
server.listen()
server.setblocking(False) # 默认为阻塞,设置为False 表示非阻塞 # 用来存储客户端的列表
clients = []
# 用来存储需要发送的数据和客户端对象
msgs = [] # 链接客户端的循环
while True:
try:
client, addr = server.accept() # 接收三次握手信息
# 如果有人链接成功,那么就把客户端对象添加到列表
clients.append(client)
except BlockingIOError as e:
# 实验效果,设置等待时间
time.sleep(0.01) # 收取数据的操作,遍历客户端列表,此处因为如果客户端
# 将链接断开,那么就不能存在列表中了,所以需要删除,
# 而并不能在for 循环中不能操作原列表,所以切片,会得到一个新的列表
for c in clients[:]:
try: # 可能这个客户端还没没有数据过来
# 开始通讯任务
data = c.recv(2048)
if not data:
c.close()
# 如果客户端断开,会一直收空。所以直接删除该客户端
clients.remove(c)
# c.send(data.upper()) # 此处如果这样写。如果缓存区满了,这个数据就丢了
# 由于此处捕获了异常,所以因该单独来处理发送数据
msgs.append((c, data)) # 将客户端对象与需要发送的信息以元祖的格式存放至字典中
except BlockingIOError as e:
pass
# print('这个客户端还不需要处理。。。。')
except ConnectionResetError:
# 断开后删除这个客户端
c.close()
clients.remove(c) # 制作发送数据的操作
# 遍历存放客户端对象与需要发送信息的列表,然后将信息发送给客户端
for i in msgs[:]:
try:
c, msg = i # 因为i存储的两个数据,是元祖,所以使用解压赋值
c.send(msg.upper())
msgs.remove(i) # 如果发送成功! 删除这个客户端对象与数据
except BlockingIOError:
pass
Vode
3.多路复用

案例: 使用select 模块
import socket
import time
import select # 使用select模块来实现
server = socket.socket()
server.bind(('192.168.13.29', 8080))
server.listen() '''
select需要三个参数
参数1:rlist 里面存储需要被检测是否可读(是否可以执行recv)的socket对象
参数2:wlist 里面存储需要被检测是否可写(是否可以执行send)的socket对象
参数3:xlist存储你需要关注异常条件,忽略即可
参数4:timeout 检测超时时间,一段时间后还是没有可以被处理的socket 那就返回空列表
返回值: 三个列表
1. 已经有数据到达的socket对象
2. 可以发送数据的socket对象
3.忽略。。。。。
'''
# 此处之所以添加server 是把server添加到select中检测是否有用户连接
rlist = [server, ] # 存储要发送的数据和socket
wlist = [] # 要发送的数据和客户端的socket
msgs = [] while True:
# 传入select所需的三个参数,返回的是有数据到达,或者可以发送数据的socket对象
ras, was, _ = select.select(rlist, wlist, []) # 阻塞直到socket可读或是可写
# 处理可读的socket
for s in ras:
# 判断列表中的s等于服务器的对象,那么就进行三次握手
if s == server:
client, addr = server.accept()
# 然后将客户端的套接字对象添加到rlist列表中
rlist.append(client)
else:
# 如果是客户端套接字对象
try:
# 那么就收数据
data = s.recv(2048)
if not data:
raise ConnectionResetError()
# 将客户端套接字对象存入待检测的wlist列表中
wlist.append(s)
# 将客户端套接字的对象与要发送的数据添加到msgs列表中
msgs.append((s, data))
except ConnectionResetError:
s.close()
rlist.remove(s)
if s in wlist: wlist.remove(s)
# 处理可写的socket,遍历检测后的was,
for s in was:
# 再遍历要发送的数据列表
for msg in msgs[:]:
# 如果需要发送的客户端等于需要发送数据的客户端
if msg[0] == s:
# 就将数据发送给这个客户端
s.send(msg[1].upper())
# 发送成功之后,删除已经无用的数据,并且需要将socket从wlist列表中删除
# 不删除会造成死循环,因为socket一直处于可写状态
msgs.remove(msg)
wlist.remove(s)
IO模型,非阻塞IO模型,select实现多路复用的更多相关文章
- 事件驱动模型 IO多路复用 阻塞IO与非阻塞IO select epool
一.事件驱动 1.要理解事件驱动和程序,就需要与非事件驱动的程序进行比较.实际上,现代的程序大多是事件驱动的,比如多线程的程序,肯定是事件驱动的.早期则存在许多非事件驱动的程序,这样的程序,在需要等待 ...
- 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO
同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出 ...
- 转 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO
此文章为转载,如有侵权,请联系本人.转载出处,http://blog.chinaunix.net/uid-28458801-id-4464639.html 同步(synchronous) IO和异步( ...
- 并发编程 - IO模型 - 1.io模型/2.阻塞io/3.非阻塞io/4.多路复用io
1.io模型提交任务得方式: 同步:提交完任务,等结果,执行下一个任务 异步:提交完,接着执行,异步 + 回调 异步不等结果,提交完任务,任务执行完后,会自动触发回调函数同步不等于阻塞: 阻塞:遇到i ...
- 5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO
POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...
- Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO
背景 整理之前学习socket编程的时候复习到了多路复用,搜索了有关资料,了解到多路复用也有局限性,本着打破砂锅问到底的精神,最终找到了关于IO模型的知识点. 在<Unix网络编程>一书中 ...
- 网络IO模型 非阻塞IO模型
网络IO模型 非阻塞IO模型 同步 一件事做完后再做另一件事情 异步 同时做多件事情 相对论 多线程 多进程 协程 异步的程序 宏观角度:异步 并发聊天 阻塞IO 阻塞IO的问题 一旦阻塞就不能做其他 ...
- 简述同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别
POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...
- Python_阻塞IO、非阻塞IO、IO多路复用
0.承上 进程: 计算机里最小的资源分配单位: 数据隔离, 利用多核,数据不安全. 线程: 计算机中最小的CPU调度单位: 数据共享,GIL锁,数据不安全. 协程: 线程的一部分,是有用户来调度的; ...
- 同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别
POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...
随机推荐
- python中else与finally的总结
1.else的用法 对try...except的补充: else子句的使用比在子句中添加其他代码更好,try因为它避免了意外捕获由try... except语句保护的代码未引发的异常. for arg ...
- react-native-page-scrollview 的使用方法(实现酷炫的分页轮播效果,还支持自定义View)
react-native-page-scrollview 对ScrollView的封装,可以很方便的实现水平,垂直分页轮播效果.而且可以自定义分页宽高,和侧边View的旋转,透明度,大小等. 对于原生 ...
- HDU 5936 Difference ( 2016 CCPC 杭州 D && 折半枚举 )
题目链接 题意 : 给出一个 x 和 k 问有多少个 y 使得 x = f(y, k) - y .f(y, k) 为 y 中每个位的数的 k 次方之和.x ≥ 0 分析 : f(y, k) - y = ...
- CentOS重新安装yum
1.问题描述 有时会出现yum不可用的错误,可以先卸载再重装. 2.操作步骤 (1).下载Python-iniparse-0.4 -9.el7.noarch.rpm (2).下载yum-3.4. ...
- Go程序的一生是怎样的?
Go 程序是怎样跑起来的 原创: 饶全成 码农桃花源 刚开始写这篇文章的时候,目标非常大,想要探索 Go 程序的一生:编码.编译.汇编.链接.运行.退出.它的每一步具体如何进行,力图弄清 Go 程序 ...
- codeforces#1196F. K-th Path(最短路,思维题)
题目链接: https://codeforces.com/contest/1196/problem/F 题意: 在无向图的所有最短路点对中,求出第$k$大 数据范围: $ 1 \leq k \leq ...
- MySQL原理解析
逻辑架构 MySQL逻辑架构整体分为三层: 客户端层,连接处理.授权认证.安全等功能均在这一层处理. 核心服务层,包括查询解析.分析.优化.缓存.内置函数(比如:时间.数学.加密等函数).所有的跨存储 ...
- html,css,js实现的一个钟表
效果如图: 实现代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...
- elasticsearch Delete (根据条件删除)
之前在 2.X版本里 这个Delete By Query功能被去掉了 因为官方认为会引发一些错误 如需使用 需要自己安装插件. bin/plugin install delete-by-query 需 ...
- JavaScript设计模式—装饰器模式
装饰器模式介绍 为对象添加新的功能,不改变其原有的结构和功能,原有的功能还是可以使用,跟适配器模式不一样,适配器模式原有的已经不能使用了,装饰器示例比如手机壳 UML类图和代码示例 Circle示原来 ...