python--io多路复用之select实现
1、I/O多路复用指:通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。
	2、I/O多路复用避免阻塞在io上,原本为多进程或多线程来接收多个连接的消息变为单进程或单线程保存多个socket的状态后轮询处理。
select
select是通过系统调用来监视一组由多个文件描述符组成的数组,通过调用select()返回结果,数组中就绪的文件描述符会被内核标记出来,然后进程就可以获得这些文件描述符,然后进行相应的读写操作
select的实际执行过程如下:
1、select需要提供要监控的数组,然后由用户态拷贝到内核态。
2、内核态线性循环监控数组,每次都需要遍历整个数组。
3、内核发现文件描述符状态符合操作结果,将其返回。
所以对于我们监控的socket都要设置为非阻塞的,只有这样才能保证不会被阻塞。
优点
基本各个平台都支持
缺点
1、每次调用select,都需要把fd集合由用户态拷贝到内核态,在fd多的时候开销会很大
2、单个进程能够监控的fd数量存在最大限制,因为其使用的数据结构是数组。
3、每次select都是线性遍历整个数组,当fd很大的时候,遍历的开销也很大
python使用select
语法:r_list, w_list, e_list = select.select( rlist, wlist, errlist [,timeout] )
说明详解:
rlist,wlist和errlist均是waitable object; 都是文件描述符,就是一个整数,或者一个拥有返回文件描述符的函数fileno()的对象。
rlist: 等待读就绪的文件描述符数组
wlist: 等待写就绪的文件描述符数组
errlist: 等待异常的数组
在linux下这三个列表可以是空列表,但是在windows上不行
当rlist数组中的文件描述符发生可读时(调用accept或者read函数),则获取文件描述符并添加到r数组中。
当wlist数组中的文件描述符发生可写时,则获取文件描述符添加到w数组中
当errlist数组中的文件描述符发生错误时,将会将文件描述符添加到e队列中
当超时时间没有设置时,如果监听的文件描述符没有任何变化,将会一直阻塞到发生变化为止
当超时时间设置为1时,如果监听的描述符没有变化,则select会阻塞1秒,之后返回三个空列表。 如果由变化,则直接执行并返回。
一、基于select实现的IO多路复用的基础实例:
io_server.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
IO多路复用服务器端
"""
import socket sk1 = socket.socket()
sk1.bind(('127.0.0.1', 8001))
sk1.listen(5) sk2 = socket.socket()
sk2.bind(('127.0.0.1', 8002))
sk2.listen(5) sk3 = socket.socket()
sk3.bind(('127.0.0.1', 8003))
sk3.listen(5) inputs = [sk1, sk2, sk3]
import select while True:
#[sk1, sk2, sk3],select内部启动监听sk1, sk2, sk3三个对象,一旦某个句柄发生变化
#如果有人用sk1
#r_list = [sk1, sk2, sk3]
r_list, w_list, e_list = select.select(inputs, [], [], 1)
print(r_list)
for sk in r_list:
#每一个连接对象
conn, address = sk.accept()
conn.sendall(bytes('Hello', encoding='utf-8'))
conn.close()
io_client.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
客户端1,请求8001端口
"""
import socket ck = socket.socket()
ck.connect(('127.0.0.1', 8001)) content = str(ck.recv(1024), encoding='utf-8')
print(content)
二、IO多路复用服务器端升级改造后的代码实现
io_server2.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
IO多路复用服务器端升级改造
""" import socket
import select sk = socket.socket() sk.bind(('127.0.0.1', 8001))
sk.listen() inputs = [sk,]
while True:
r_list, w_list, e_list = select.select(inputs, [], [], 1)
print('正在监听的socket对象:%d' % len(inputs))
for sk_or_conn in r_list:
#每一个连接对象
if sk_or_conn == sk:
#表示有新用户来连接
conn, address = sk.accept()
inputs.append(conn)
else:
#有老用户发消息了
try:
data_bytes = sk_or_conn.recv(1024)
except Exception as ex:
#如果有用户终断连接,则移除句柄
inputs.remove(sk_or_conn)
else:
#用户正常发送信息
data_str = str(data_bytes, encoding='utf-8')
sk_or_conn.sendall(bytes(data_str + '好', encoding='utf-8')) for sk in e_list:
inputs.remove(sk)
三、IO多路复用服务器端升级改造,读、写分离
io_server3.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
IO多路复用服务器端升级改造,读、写分离
""" import socket
import select sk = socket.socket()
sk.bind(('127.0.0.1', 8001))
sk.listen() inputs = [sk,]
outputs = []
message_dict = {} while True: r_list, w_list, e_list = select.select(inputs, outputs, inputs, 1) print('正在监听的socket对象:%d' % len(inputs))
for sk_or_conn in r_list:
#每一个连接对象
if sk_or_conn == sk:
#表示有新用户来连接
conn, address = sk.accept()
inputs.append(conn)
#将连接的用户添加到字典中
message_dict[conn] = []
else:
#有老用户发消息了
try:
data_bytes = sk_or_conn.recv(1024)
except Exception as ex:
#如果有用户终断连接,则移除句柄
inputs.remove(sk_or_conn)
else:
# 用户正常发送信息
data_str = str(data_bytes, encoding='utf-8')
message_dict[sk_or_conn].append(data_str) #将用户发送过来的信息存在在字典中
# sk_or_conn.sendall(bytes(data_str + '好', encoding='utf-8'))
outputs.append(sk_or_conn) #写操作
for sk_out in w_list:
recv_data = message_dict[sk_out][0] #从字典中获取信息数据
del message_dict[sk_out][0] #获取数据后,清空字典,等待存储下次的数据
sk_out.sendall(bytes(recv_data + '好', encoding='utf-8'))
outputs.remove(sk_out) for sk in e_list:
inputs.remove(sk)
python--io多路复用之select实现的更多相关文章
- Python——IO多路复用之select模块epoll方法
		
Python——IO多路复用之select模块epoll方法 使用epoll方法实现IO多路复用,使用方法基本与poll方法一致,epoll效率要高于select和poll. .├── epoll_c ...
 - Python——IO多路复用之select模块poll方法
		
Python——IO多路复用之select模块poll方法 使用poll方法实现IO多路复用 .├── poll_client.py├── poll_server.py└── settings.py ...
 - Python——IO多路复用之select模块select方法
		
Python——IO多路复用之select模块select方法 使用select模块的select方法实现Python——IO多路复用 实现同时将终端输入的文本以及客户端传输的文本写入文本文件中: w ...
 - python网络编程——IO多路复用之select
		
1 IO多路复用的概念 原生socket客户端在与服务端建立连接时,即服务端调用accept方法时是阻塞的,同时服务端和客户端在收发数据(调用recv.send.sendall)时也是阻塞的.原生so ...
 - 【python】--  IO多路复用(select、poll、epoll)介绍及实现
		
IO多路复用(select.poll.epoll)介绍及select.epoll的实现 IO多路复用中包括 select.pool.epoll,这些都属于同步,还不属于异步 一.IO多路复用介绍 1. ...
 - IO多路复用(select、poll、epoll)介绍及select、epoll的实现
		
IO多路复用(select.poll.epoll)介绍及select.epoll的实现 IO多路复用中包括 select.pool.epoll,这些都属于同步,还不属于异步 一.IO多路复用介绍 1. ...
 - IO多路复用之select
		
IO多路复用之select总结 1.基本概念 IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程.IO多路复用适用如下场合: (1)当客户处理多个描述字时(一般是交 ...
 - 网络通信 --> IO多路复用之select、poll、epoll详解
		
IO多路复用之select.poll.epoll详解 目前支持I/O多路复用的系统调用有 select,pselect,poll,epoll,I/O多路复用就是通过一种机制,一个进程可以监视 ...
 - IO多路复用之select、poll、epoll
		
本文转载自IO多路复用之select.poll.epoll 导语 IO多路复用:通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. ...
 - python基础-11 socket,IO多路复用,select伪造多线程,select读写分离。socketserver源码分析
		
Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...
 
随机推荐
- SpringBoot扩展点之一:SpringApplicationRunListener
			
三种监听器的关系 ApplicationListener.SpringApplicationRunListeners.SpringApplicationRunListener的关系: SpringAp ...
 - 【搬运工】RHEL6.5 移植使用CentOS 的YUM 步骤
			
转载地址:http://www.cnblogs.com/rchen98/p/6056469.html 问题:使用 Red Hat Enterprise Linux Server(RHEL) yum安装 ...
 - 【Pandas教程】像写SQL一样用Pandas~
			
写在最前 Python在数据分析领域有三个必须需要熟悉的库,分别是pandas,numpy和matplotlib,如果排个优先级的话,我推荐先学pandas. numpy主要用于数组和矩阵的运算,一般 ...
 - 1、VUE介绍
			
1.VUE简介 最近一段时间,Web前端领域出现了很多MVVM框架技术,如AngularJS.React,VUE.js等等. Vue.js借鉴了AngularJS的设计理念,也吸取了React和Ang ...
 - java基础 接口静态方法
			
/** * 从java8开始,接口当中允许定义静态方法 * 格式: * public static 返回值类型 方法名称(参数列表){ * 方法体 * } * 提示:就是将abstract或者defa ...
 - .net core Identity注册用户 出错
			
使用微软自带的注册 报 NotSupportedException: No IUserTwoFactorTokenProvider<TUser> named 'Default' is re ...
 - 经实验验证,修正对using namespace std的认识
			
备注①:name:符号.指的实体包括:变量.函数.类 备注②:认为全局命名空间也是一个包,在此称作 ROOT:: 或 global:: (这样就有了两个特别的包:一个是全局包,一个是std包.但对于编 ...
 - 1-python运算符和逻辑控制语句
			
目录 运算符 条件语句if…else 断言assert 循环语句while 遍历for循环 1.运算符 1.1.算数运算符 加+.减-.乘*.除/.余%.次方**.向下取整除// 1.2.赋值运算符 ...
 - WC2018 文艺汇演《退役的你》
			
视频网址:https://www.bilibili.com/video/av19333297 谨以此歌献给那些曾与我们并肩前行的退役 OIer 填词 & 视频:Menci 演唱:wxh0109 ...
 - Java自学-接口与继承 重写
			
Java 重写方法 子类可以继承父类的对象方法 在继承后,重复提供该方法,就叫做方法的重写 又叫覆盖 Override 步骤 1 : 父类Item 父类Item有一个方法,叫做effect packa ...