在socket的通信中,recv,accept,recvfrom(UDP协议接收信息)这些阶段由于需要收到信息,才能继续下面的代码,所以这些阶段叫做阻塞,类似于
我们python变成中的input函数,time.sleep方法,在socket通信中,这些阻塞会使进程进入到阻塞状态,下次再进入运行状态时要消耗内存,所以解决
阻塞可以提高我们代码的执行效率和节省内存空间。下面以访问文件为例,看几种典型的IO模式

一、阻塞IO
经历了两个阻塞阶段
1.发送方:发出去的请求之后等待回应
2.接收方:收到请求,整理数据,从内核拷贝到进程里
这是最原始的IOmodel,记住这两个阻塞阶段,后面的IO模型都是基于这两点做该进的。

当然,我们可以开起多线程,多进程的方式,在阻塞的时间里处理其他的事情,但是当线程、进程开到很多的时候会占用系统资源,降低系统响应速率。
当规模比较大时,这种方法就不适合选择了。

二、非阻塞IO

import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9000))
sk.setblocking(False)
sk.listen()
conn_l = [] # 已连接的客户端列表
del_conn = []
while True:
try:
conn,addr = sk.accept() #不阻塞,但是没人连我会报错
print('建立连接了:',addr)
conn_l.append(conn) #将连接过的加入列表,便于提取下次客户端第二次发送信息
except BlockingIOError:
for con in conn_l:
try:
msg = con.recv(1024) # 非阻塞,如果没有数据就报错
if msg == b'':
del_conn.append(con)
continue
print(msg)
con.send(b'byebye')
except BlockingIOError:pass
for con in del_conn:
con.close()
conn_l.remove(con)
del_conn.clear()

server端

import time
import socket
from threading import Thread def func():
sk = socket.socket()
sk.connect(('127.0.0.1',8080))
time.sleep(0.1) # 模拟阻塞
sk.send(b'hello')
time.sleep(0.5) # 模拟接收消息过程
msg = sk.recv(1024)
print(msg)
sk.close() for i in range(10):
t = Thread(target=func)
t.start()

client端

依次启动服务端,客户端 服务端
收到客户端连接并加入conn_l列表,由于客户端设置了一个发消息之前设置了一个sleep,并且服务端set.blocking=False,
服务端while循环时未取到accept会进入注释为‘1’的异常处理,查询conn_1后,接收到客户端完成sleep发来的信息。但此时会接收到一系列的
b'',(同时未取到信息会报错,捕捉并且不作处理)因为客户端已经发送完成,没有消息了,服务端recv都是空,应该判断msg是否为b'',
并将这个连接加入到删除列表,循环完成后删除。

但是用while轮询时,非常占用内存,导致系统处理变慢,响应速率降低。

三、IO多路复用

IO多路复用模型是socket服务端借助了操作系统来完成的,操作系统会监听访问者,一旦收到连接请求,操作系统来给socket服务端提供信号,让其进入accept阶段,向下继续执行,使其变为非阻塞状态,同时也会将文件拷贝至进程,让其recv。这种用于socket端比较多的情况,因为比起阻塞IO,多路复用增加了一个系统与socket之间的相互通信。但是如果监听的socket较多的话,效率还是很快的。

import select   # select模块是操作系统用来监听的模块
import socket sk = socket.socket()
sk.bind(('127.0.0.1',8000))
sk.setblocking(False)
sk.listen() read_lst = [sk] # 将需要监听的sk加入列表
while True: # [sk,conn]
r_lst,w_lst,x_lst = select.select(read_lst,[],[]) # 返回的是三个值,分别为是哪个socket可读,可写,可改
# 一旦有文件可以读取,就会返回该socket的地址
for i in r_lst:
if i is sk:
conn,addr = i.accept()
read_lst.append(conn) # socket可连接的客户端链接地址
else:
ret = i.recv(1024)
if ret == b'':
i.close()
read_lst.remove(i)
continue
print(ret)
i.send(b'goodbye!')

服务端server

相较于非阻塞IO,可以监听多个socket,并且不用多次轮询,优化了内存使用

补充一点,代码中的select是windows系统用的,还有Linux的poll模块,监听的数量要比select多,以及Linux的epolled模块,不仅起到监听socket对象的作用,而且还会给每个对象加上一个回调函数。windows中的selector模块和其作用相似。

在监听的对象成百上千时,由于数据类型是列表,数量越多查询速度越慢,但是使用epoll一旦准备好可以读取,可以调用它的回调函数直接来发送信号给socket,速率更高。

四、异步IO

异步IO原理是 用户端发送读取请求,不进入阻塞,可以做不相干的业务逻辑,将请求发给操作系统执行,操作系统完成文件的recv和提取到进程的过程,用户端直接读取。

但由于python端没有可以直接操作系统的接口,所以目前大部分异步IO都是由C语言完成。

常见IO模型的更多相关文章

  1. 京东数科二面:常见的 IO 模型有哪些?Java 中的 BIO、NIO、AIO 有啥区别?

    IO 模型这块确实挺难理解的,需要太多计算机底层知识.写这篇文章用了挺久,就非常希望能把我所知道的讲出来吧!希望朋友们能有收货!为了写这篇文章,还翻看了一下<UNIX 网络编程>这本书,太 ...

  2. 京东数科面试真题:常见的 IO 模型有哪些?Java 中的 BIO、NIO、AIO 有啥区别?

    本文节选自<Java面试进阶指北 打造个人的技术竞争力> 面试中经常喜欢问的一个问题,因为通过这个问题,面试官可以顺便了解一下你的操作系统的水平. IO 模型这块确实挺难理解的,需要太多计 ...

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

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

  4. Linux下常见的IO模型

    前言 阻塞IO(blocking IO) 非阻塞IO(nonblocking IO) IO复用(IO multiplexing) 异步IO(asynchronous IO (the POSIX aio ...

  5. 高性能IO模型浅析

    高性能IO模型浅析 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型. (2)同步非阻塞IO(Non-blocking  ...

  6. Linux下5种IO模型的小结

    概述 接触网络编程,我们时常会与各种与IO相关的概念打交道:同步(Synchronous).异步(ASynchronous).阻塞(blocking)和非阻塞(non-blocking).关于概念的区 ...

  7. 操作系统IO模型

    操作系统IO模型 声明:如下内容是根据APUE和mycat两本著作中关于I/O模式的一些内容加上自己的一些理解整理而成,仅供学习使用. 本节内容 UNIX下可用的五种I/O模型 三种I/O模型 Rea ...

  8. 服务器端高性能的IO模型 转自酷勤网

    服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(BlockingIO):即传统的IO模型. (2)同步非阻塞IO(Non-blockingIO):默认创建的soc ...

  9. 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO

    同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出 ...

随机推荐

  1. JS引擎的执行机制:探究EventLoop(含Macro Task和Micro Task)

    在我看来理解好JS引擎的执行机制对于理解JS引擎至关重要,今天将要好好梳理下JS引擎的执行机制. 首先解释下题目中的名词:(阅读本文后你会对这些概念掌握了解) Event Loop:事件循环Micro ...

  2. javascript 之 面向对象【理解对象】

    第五版本 6.1.1  属性类型      1/数据属性 :包含有数据值的问题.有内部有特性和属性,是为了实现javaScript引擎用的,在javaScript中不能直接访问  [[Configur ...

  3. 【我的前端自学之路】【HTML5】web 存储

    以下为自学笔记内容,仅供参考. 转发请保留原文链接:https://www.cnblogs.com/it-dennis/p/10503539.html 什么是Web存储 cookie最大的缺陷是在每一 ...

  4. LINUX之根目录介绍、普通目录创建、删除、复制、移动、权限管理命令记录

    (一)Linux 系统目录结构 登录系统后,在当前命令窗口下输入命令:ls / /bin:bin是Binary的缩写, 这个目录存放着最经常使用的命令. /boot:这里存放的是启动Linux时使用的 ...

  5. showdoc 自动脚本安装

    ========================== showdoc 简介==========================在线文档管理系统很多, 比如阿里的语雀.腾讯的 TAPD 平台也包括文档管 ...

  6. Ant Design of React 框架使用总结1

    一.  为什么要用UI 框架 统一了样式交互动画 . Ui框架会对样式,交互动画进行统一,保证了系统风格完整统一,不像拼凑起来的. 兼容性 ,不是去兼容IE 6 7 8那些低版本浏览器,而是对主流的标 ...

  7. Java多线程之volatile关键字《一》

    关键字volatile的主要作用是使变量在多个线程间可见. 1.关键字volatile与死循环 如果不是在多继承的情况下,使用继承Thread类和实现Runnable接口在取得程序运行的结果上并没有什 ...

  8. Spring Cloud 升级最新 Finchley 版本,踩了所有的坑!

    Spring Boot 2.x 已经发布了很久,现在 Spring Cloud 也发布了 基于 Spring Boot 2.x 的 Finchley 版本,现在一起为项目做一次整体框架升级. 升级前 ...

  9. Python自学:第三章 使用del语句删除元素

    motorcycles = ["honda", "yamaha", "suzuki"] print(motorcycles) del mot ...

  10. 双重ScrollView,RecyclerView联动实例

    最近收到一个需求,如图,大家一看,不就是一个简单的表格吗,RecyclerView就搞定了 我一开始也是这么想的,但是当我继续听下去 需求是左边党支部栏目只能上下滑动,之后联动右边下方表格一起上下滑动 ...