IO阻塞模型、IO非阻塞模型、多路复用IO模型
IO操作主要包括两类:
本地IO
网络IO
本地IO:本地IO是指本地的文件读取等操作,本地IO的优化主要是在操作系统中进行,我们对于本地IO的优化作用十分有限
网络IO:网络IO指的是在进行网络操作时需要等待用户的输入及传输的等待等,网络IO的优化需要我们自己进行,而我们对于网络IO的优化主要在等待用户输入时程序可以继续运行
1、IO阻塞模型
什么是IO阻塞模型
在我们使用socket创建客户端、服务端时,如果不对 他们执行其他操作,那么客户端的recv、send和服务器端的accept、send、recv等都是阻塞的,只有等到有数据传输过来或者有客户端连接过来时才会操作,否则就会进入等待状态,这种模型就是IO阻塞模型
IO阻塞模型的缺点
使用IO阻塞模型时,客户端的影响较小,但是对于服务器端,由于要处理多个客户端的请求,所以如果使用阻塞模型,那么同一时间只能有一个客户端进行连接,效率十分低,不能进行并发
2、IO非阻塞模型
什么是IO非阻塞模型
由于在使用网络IO时,在不进行任何处理的情况下默认是会阻塞的,但是如果不想程序进行阻塞,此时可以通过设置setblocking
来实现,这样在进行原本会阻塞的操作时,如果有数据就会对数据进行处理,如果没有数据则会直接报错,只要进行异常的捕捉就能使程序进行后续代码的执行,这样可以实现IO非阻塞
示例代码:
客户端
- import socket
-
- client = socket.socket()
- client.connect(("127.0.0.1",1688))
-
- while True:
- msg = input("msg:").strip()
- if not msg:
- continue
- try:
- client.send(msg.encode("utf-8"))
- recv_msg = client.recv(2048)
- print(recv_msg.decode("utf-8"))
- except ConnectionResetError:
- print("客户端意外关闭")
- break
服务器
- import socket
-
- server = socket.socket()
- server.bind(("127.0.0.1",1688))
- server.listen()
- server.setblocking(False)
-
- conn_list = []
- msg_list = []
-
- while True:
- try:
- conn,addr = server.accept()
- conn_list.append(conn)
- except BlockingIOError:
- print("还没有客户端连接")
- for conn in conn_list:
- try:
- msg = conn.recv(1024)
- msg_list.append((conn,msg))
- except BlockingIOError:
- print("该用户没有数据传输过来")
- for msg_t in msg_list:
- conn,msg = msg_t
- try:
- conn.send(msg.upper())
- msg_list.remove(msg_t)
- except ConnectionResetError:
- print("信息无法发送")
- conn.close()
- conn_list.remove(conn)
IO非阻塞模型的缺点
使用IO非阻塞模型,我们解决了不能实现并发的缺点,在一个线程中实现了并发,但是IO非阻塞模型存在一些问题,最主要的问题是,在使用非阻塞模型时,由于需要不停的进行询问,所以会持续的消耗系统的CPU资源,造成不必要的CPU占用
3、多路复用IO模型
在使用非阻塞IO模型处理问题时,虽然解决了不能在单个线程中实现并发的问题,但是由于需要不停的进行询问,所以就会造成CPU的不必要占用,造成CPU占用过高的问题
什么是多路复用IO模型
多路复用IO模型指的是多个TCP连接使用一个或者少量的线程来实现通信的IO模型,在IO非阻塞模型中,我们是通过自己不停的使用send()
或者recv()
来不停的询问是否有数据需要进行操作,在多路复用IO模型中,我们使用select
统一的来进行询问,并将可以进行操作的对象放到一个列表中进行统一管理,并且select
还可以区分那些是可以发送数据的对象,哪些是可以接收数据的对象,并放在不同的列表中进行统一管理
示例代码:
客户端
- import socket
-
- client = socket.socket()
- client.connect(("127.0.0.1",1688))
-
- while True:
- try:
- msg = input("msg:").strip()
- if not msg:
- continue
- client.send(msg.encode("utf-8"))
- recv_msg = client.recv(1024).decode("utf-8")
- print(recv_msg)
- except ConnectionResetError:
- print("服务器已关闭")
- break
服务器端
- import socket
- import select
-
- server = socket.socket()
- server.bind(("127.0.0.1",1688))
- server.listen()
-
- r_list = [server,]
- w_list = []
- msg_list = []
- while True:
- readable_list,writeable_list,_ = select.select(r_list,w_list,[])
- for conn in readable_list:
- if conn == server:
- conn,addr = conn.accept()
- r_list.append(conn)
- else:
- try:
- msg = conn.recv(1024)
- if not msg:
- raise ConnectionResetError
- msg_list.append((conn,msg))
- w_list.append(conn)
- except ConnectionResetError:
- print("%s客户端正常关闭" %conn)
- r_list.remove(conn)
- if conn in w_list:
- w_list.remove(conn)
- conn.close()
- for conn in w_list:
- for msg_t in msg_lis[:]:
- connection,msg = msg_t
- if conn == connection:
- try:
- connection.send(msg.upper())
msg_list.remove(msg_t)- except ConnectionResetError:
- msg_list.remove(msg_t)
- w_list.remove(conn)
-
- msg_list.remove(msg_t)
- w_list.remove(conn)
多路复用的缺点:
使用多路复用解决了在非阻塞IO中出现的CPU占用过高的问题,但是在多路复用中也出现了几个问题:
使用select时最多只能处理1024个客户端,如果数量多与此值,那么就会直接就会报错
如果发送的数据量特别大的情况下只能处理一个客户端,其它的客户端只能进行等待
IO阻塞模型、IO非阻塞模型、多路复用IO模型的更多相关文章
- Python之阻塞IO模型与非阻塞IO模型
Python之阻塞IO模型与非阻塞IO模型 IO模型 1 阻塞IO: 全程阻塞 2 非阻塞IO: 发送多次系统调用: 优点:wait for data时无阻塞 缺点:1 系统调用太多 2 数据不是实时 ...
- 五种I/O 模式——阻塞(默认IO模式),非阻塞(常用语管道),I/O多路复用(IO多路复用的应用场景),信号I/O,异步I/O
五种I/O 模式——阻塞(默认IO模式),非阻塞(常用语管道),I/O多路复用(IO多路复用的应用场景),信号I/O,异步I/O 五种I/O 模式:[1] 阻塞 I/O ...
- 如何解读 Java IO、NIO 中的同步阻塞与同步非阻塞?
原文链接:如何解读 Java IO.NIO 中的同步阻塞与同步非阻塞? 一.前言 最近刚读完一本书:<Netty.Zookeeper.Redis 并发实战>,个人觉得 Netty 部分是写 ...
- 阻塞式和非阻塞式IO
有很多人把阻塞认为是同步,把非阻塞认为是异步:个人认为这样是不准确的,当然从思想上可以这样类比,但方式是完全不同的,下面说说在JAVA里面阻塞IO和非阻塞IO的区别 在JDK1.4中引入了一个NIO的 ...
- Java IO(3)非阻塞式输入输出(NIO)
在上篇<Java IO(2)阻塞式输入输出(BIO)>的末尾谈到了什么是阻塞式输入输出,通过Socket编程对其有了大致了解.现在再重新回顾梳理一下,对于只有一个“客户端”和一个“服务器端 ...
- Socket 阻塞模式和非阻塞模式
阻塞I/O模型: 简介:进程会一直阻塞,直到数据拷贝 完成 应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好. 如果数据没有准备好,一直等待….数据准备好了,从内核拷贝到用户空间,IO函数返 ...
- Linux下同步模式、异步模式、阻塞调用、非阻塞调用总结
转自:http://www.360doc.com/content/13/0117/12/5073814_260691714.shtml 同步和异步:与消息的通知机制有关. 本质区别 现实例子 同步模式 ...
- 斐讯面试记录—阻塞Socket和非阻塞Socket
文章出自:http://blog.csdn.net/VCSockets/ 1.TCP中的阻塞Socket和非阻塞Socket 阻塞与非阻塞是对一个文件描述符指定的文件或设备的两种工作方式. 阻塞的意思 ...
- 简单测试Java线程安全中阻塞同步与非阻塞同步性能
摘抄自周志明老师的<深入理解Java虚拟机:JVM高级特性与最佳实践>13.2.2 线程安全的实现方法 1.名词解释 同步是指锁哥线程并发访问共享数据时,保证共享数据同一时刻只被一个线程访 ...
- socket异步通信-如何设置成非阻塞模式、非阻塞模式下判断connect成功(失败)、判断recv/recvfrom成功(失败)、判断send/sendto
socket异步通信-如何设置成非阻塞模式.非阻塞模式下判断connect成功(失败).判断recv/recvfrom成功(失败).判断send/sendto 博客分类: Linux Socket s ...
随机推荐
- C#中'??'符的使用
?? 用于判断当前对象是否为null. 语法: 对象 ?? "当前对象为null时赋的默认值". string nullString = null; string Kong = ...
- linux下解决安装jdk后‘环境变量’不生效的问题
1.是否需要配置环境变量,主要看java -version 显示的版本是否为你期望的版本: (1)不需要配置环境变量的情况 使用java -version查看,版本显示正好是你刚刚安装的版本,这一般为 ...
- 第八章 用SQL语句操作数
--切换数据库:手动切换和命令切换 use MySchool --向Student表中插入数据 --语法:INSERT [INTO] 表名 (列名) VALUES (值列表) --注意事项: --1. ...
- Collection接口详解
Collection 介绍 https://blog.csdn.net/jyg0723/article/details/80498840 Stream API介绍 https://www.jians ...
- Linux之文件通信
/* * 后执行,尝试读取另外一个进程写入文件的内容 */ #include <stdio.h> #include <unistd.h> #include <stdlib ...
- P3368 【模板】树状数组 2
原题链接 https://www.luogu.org/problemnew/show/P3368 这个题和洛谷P3374树状数组1 有些不同,在普通的树状数组上运用了差分的知识.(由于P3374涉及 ...
- 和证书相关的文件格式: Pem, Pfx, Der
Pem Pem是最常见的证书文件格式.常见文件扩展名为.pem. 其文件内容采用如下格式: -----BEGIN CERTIFICATE----- Base64编码的证书内容-----END CERT ...
- JavaWeb_(Spring框架)Spring中的aop事务
1.事务相关知识 a)什么是事务:把多条数据库操作捆绑到一起执行,要么都成功,要么都失败: b)事务的原则ACID: i.原子性:事务包含的所有操作,要么全部成功,要么全部失败回滚,成功全部应用到数据 ...
- Spring框架IOC解说
控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合.当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象.你可以认为IoC与JN ...
- zabbix :web 界面显示的监控项值为0或者空
[参考文章]:[错误汇总]zabbix_get 的值一直为 0 1. 问题现象 zabbix 版本:3.4: server 端部署在 192.168.145.134 ,agent 节点部署在 192. ...