非阻塞套接字与IO多路复用(转,python实现版)
非阻塞:指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。epoll工作在非阻塞模式时,才会发挥作用。
我们了解了socket之后已经知道,普通套接字实现的服务端的缺陷:一次只能服务一个客户端!


并且,为了使一个客户端能够不断收发消息,我们还要使用while循环来轮询,这极大地降低了我们的效率
accept阻塞!
在没有新的套接字来之前,不能处理已经建立连接的套接字的请求
recv 阻塞!
在没有接受到客户端请求数据之前,不能与其他客户端建立连接
可以用非阻塞接口来尝试解决这个问题!
阻塞IO模型

阻塞IO(blocking IO)的特点:就是在IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被block了。
什么是阻塞呢?想象这种情形:你要去车站接朋友,到了车站之后发现车还没到站,你现在有两种选择:
- 继续在等着,直到朋友的车到站。
- 先去干点别的,然后时不时地联系你的朋友询问车是否到站,朋友说到了,你再去车站
很明显,大多数人都会选择第二种方案。
而在计算机世界,这两种情形就对应阻塞和非阻塞忙轮询。
- 非阻塞轮询:数据没来,进程就不停的去检测数据,直到数据来。
- 阻塞:数据没来,啥都不做,直到数据来了,才进行下一步的处理。
非阻塞IO模型

非阻塞套接字和阻塞套接字的区别:



把套接字设置为非阻塞之后,如果没有得到想要的数据,就会抛出一个BlockingIOError的异常。我们可以通过捕获处理这个异常,让程序正常完成
非阻塞式IO中,用户进程其实是需要不断的主动询问kernel数据准备好了没有
非阻塞如何利用
- 吃满 CPU !
- 宁可用 while True ,也不要阻塞发呆!
- 只要资源没到,就先做别的事!
编程范式:
服务端

import socket
CONN_ADDR = ('127.0.0.1', 9999)
conn_list = [] # 连接列表
server = socket.socket() # 开启socket
server.setblocking(False) # 设置为非阻塞
server.bind(CONN_ADDR) # 绑定IP和端口到套接字
server.listen(5) # 监听,5表示最大挂起数
print('start listen')
while True:
try:
conn,addr = server.accept() #等待客户端连接,没有就抛出BlockingIOError
conn.setblocking(False)
print('{}已连接'.format(addr))
conn_list.append(conn)
except BlockingIOError:
pass
conn_list = [x for x in conn_list]
for conn_socket in conn_list:#对已连接的套接字进行轮询
try:
data = conn_socket.recv(1024) #如有客户端发送消息,则打印并返回
except BlockingIOError:
pass
else: #else在不报错的时候才执行
if data: #判断客户端发过来的是不是空
print(data.decode())
conn_socket.send(data)
else: #若为空,表示客户端已断开
conn_socket.close()
conn_list.remove(conn_socket)
print('客户端数目:{}'.format(len(conn_list)))

客户端

import socket
client = socket.socket()
client.connect(('127.0.0.1',9999))
while True:
data = input('>>>>>')
if data == 'q': #按q退出
break
client.send(data.encode()) response = client.recv(1024) print(response.decode())

非阻塞IO模型优点:实现了同时服务多个客户端,能够在等待任务完成的时间里干其他活了(包括提交其他任务,也就是 “后台” 可以有多个任务在“”同时“”执行)。
但是非阻塞IO模型绝不被推荐
非阻塞IO模型缺点:
- 不停地轮询,占用较多的CPU资源。
- 对应BlockingIOError的异常处理也是无效的CPU花费 !
如何解决:多路复用IO
多路复用IO
什么是IO多路复用技术呢,简单来说,就是我们把套接字交给操作系统去监控。

使用select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视socket,以及调用select函数的额外操作,感觉效率更差。
但是,使用select以后最大的优势是用户可以在一个线程内同时处理多个socket的IO请求。用户可以注册多个socket,然后不断地调用select读取被激活的socket,
即可达到在同一个线程内同时处理多个IO请求的目的。而在同步阻塞模型中,必须通过多线程的方式才能达到这个目的。
epoll是目前Linux上效率最高的IO多路复用技术。
epoll是惰性的事件回调,惰性事件回调是由用户进程自己调用的,操作系统只起到通知的作用。
epoll实现并发服务器,处理多个客户端

import socket
import selectors # 注册一个epllo事件参数
# 1. 需要操作系统监控的套接字
# 2.事件(可读还是可写)
# 3.回调函数 def recv_data(conn):
data = conn.recv(1024) if data:
print('接收的数据是:%s' % data.decode())
conn.send(data)
else:
print('断开连接',conn)
e_poll.unregister(conn)
conn.close() def accept_conn(p_server):
conn, addr = p_server.accept()
print('Connected by', addr)
# 也要注册一个事件
e_poll.register(conn,selectors.EVENT_READ,recv_data) CONN_ADDR = ('127.0.0.1', 9999)
server = socket.socket()
server.bind(CONN_ADDR)
server.listen(6) # 生成一个epllo选择器实例 I/O多路复用,监控多个socket连接
e_poll = selectors.DefaultSelector() # Linux是epoll,Windows是select
e_poll.register(server, selectors.EVENT_READ, accept_conn) # 事件循环
while True:
# 事件循环不断地调用select获取发生变化的socket
events = e_poll.select()
for key, mask in events:
call_back = key.data #key.data就是回调函数
call_back(key.fileobj) #key.fileobj是套接字

非阻塞套接字与IO多路复用(转,python实现版)的更多相关文章
- 非阻塞套接字与IO多路复用
我们了解了socket之后已经知道,普通套接字实现的服务端的缺陷:一次只能服务一个客户端! 并且,为了使一个客户端能够不断收发消息,我们还要使用while循环来轮询,这极大地降低了我们的效率 acce ...
- 11 非阻塞套接字与IO多路复用(进阶)
1.非阻塞套接字 第一部分 基本IO模型 1.普通套接字实现的服务端的缺陷 一次只能服务一个客户端! 2.普通套接字实现的服务端的瓶颈!!! accept阻塞! 在没有新的套接字来之前,不能处理已经建 ...
- 非阻塞套接字编程, IO多路复用(epoll)
非阻塞套接字编程: server端 import socket server = socket.socket() server.setblocking(False) server.bind(('', ...
- python_非阻塞套接字及I/O流
http://www.cnblogs.com/lixy-88428977/p/9638949.html 首先,我们要明确2个问题: 普通套接字实现的服务端有什么缺陷吗? 有,一次只能服务一个客户端! ...
- C++ 非阻塞套接字的使用 (3)
异步非阻塞套接字避免了死循环的接收问题,但是软件用起来体验还是很差.究其原因,软件在指令的发送.接收上, 采取了一种不合理的方式:在指令的发送后,立刻调用接收函数,等待回令. 若是采用同步阻塞套接字, ...
- C++ 非阻塞套接字的使用 (1)
在维护代码的过程中,发现软件运行的CPU占用率居高不下,在4核的电脑上占用了25%的CPU.查阅资料的得知,这是可能是由于软件中出现了死循环. 经过对软件的一些测试,最终确定了死循环出现的位置——通讯 ...
- C++ 非阻塞套接字的使用 (2)
继续话题——软件中的异步非阻塞通讯方式. 由于软件基于MFC开发,所以实现异步通讯时使用了CAsyncSocket类. 首先要了解CAsyncSocket异步机制,引用自 http://blog.cs ...
- 五种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 ...
- 阻塞I/O、非阻塞I/O和I/O多路复用、怎样理解阻塞非阻塞与同步异步的区别?
“阻塞”与"非阻塞"与"同步"与“异步"不能简单的从字面理解,提供一个从分布式系统角度的回答.1.同步与异步 同步和异步关注的是消息通信机制 (syn ...
随机推荐
- Word文档粘贴到DEDECMS
Chrome+IE默认支持粘贴剪切板中的图片,但是我要发布的文章存在word里面,图片多达数十张,我总不能一张一张复制吧?Chrome高版本提供了可以将单张图片转换在BASE64字符串的功能.但是无法 ...
- CF576D Flights for Regular Customers 矩阵乘法 + Bitset优化
%%%cxhscst2's blog Codeforces 576D Flights for Regular Customers(矩阵加速DP) 代码非常优美 + 简洁,学习到了 Code: #inc ...
- 给网页标题添加icon小图标
so easy: 给网页标题添加icon小图标: 直接在html文件的head部分添加下面代码(注意href的路径): <link rel="icon" type=" ...
- leetcode 217. 存在重复元素 (python)
给定一个整数数组,判断是否存在重复元素. 如果任何值在数组中出现至少两次,函数返回 true.如果数组中每个元素都不相同,则返回 false. 示例 1: 输入: [1,2,3,1]输出: true示 ...
- Linux 初始化系统(init)- systemd
wikipedia 浅析 Linux 初始化 init 系统 systemd 中文手册 fedoraproject - systemd 1. Systemd 简介 Systemd 是 Linux 系统 ...
- 16/7/11_PHP-PHP异常处理
抛出一个异常 从PHP5开始,PHP支持异常处理,异常处理是面向对象一个重要特性,PHP代码中的异常通过throw抛出,异常抛出之后,后面的代码将不会再被执行. 既然抛出异常会中断程序执行,那么为什么 ...
- < 备考CET6 - 作文模板句 - 话题:重要性/做选择 >
CET6 - 作文模板句 - 重要性/做选择 重要性 开头 Currently, We are entering a brand new era filled with (opportunities ...
- 爬虫(五)—— 解析库(二)beautiful soup解析库
目录 解析库--beautiful soup 一.BeautifulSoup简介 二.安装模块 三.Beautiful Soup的基本使用 四.Beautiful Soup查找元素 1.查找文本.属性 ...
- Linux:VIM简单入手
现在的Linux系统一般都会默认安装VIM编辑器,如果没有安装VIM编辑器,也默认一定会有VI编辑器,VI编辑器产生的时间比鼠标来的更早,虽然功能很强大,但我建议安装VIM工具,安装了VIM之后,VI ...
- no suitable HttpMessageConverter found for response type
在使用 RestTemplate 或者 Spring Cloud 的时候,经常会出现这个错误. 基本上出现的场景都是,我们要json,结果来了个 text/html. 两个原因: 第一个就是:服务器返 ...