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实现的更多相关文章

  1. Python——IO多路复用之select模块epoll方法

    Python——IO多路复用之select模块epoll方法 使用epoll方法实现IO多路复用,使用方法基本与poll方法一致,epoll效率要高于select和poll. .├── epoll_c ...

  2. Python——IO多路复用之select模块poll方法

    Python——IO多路复用之select模块poll方法 使用poll方法实现IO多路复用 .├── poll_client.py├── poll_server.py└── settings.py ...

  3. Python——IO多路复用之select模块select方法

    Python——IO多路复用之select模块select方法 使用select模块的select方法实现Python——IO多路复用 实现同时将终端输入的文本以及客户端传输的文本写入文本文件中: w ...

  4. python网络编程——IO多路复用之select

    1 IO多路复用的概念 原生socket客户端在与服务端建立连接时,即服务端调用accept方法时是阻塞的,同时服务端和客户端在收发数据(调用recv.send.sendall)时也是阻塞的.原生so ...

  5. 【python】-- IO多路复用(select、poll、epoll)介绍及实现

    IO多路复用(select.poll.epoll)介绍及select.epoll的实现 IO多路复用中包括 select.pool.epoll,这些都属于同步,还不属于异步 一.IO多路复用介绍 1. ...

  6. IO多路复用(select、poll、epoll)介绍及select、epoll的实现

    IO多路复用(select.poll.epoll)介绍及select.epoll的实现 IO多路复用中包括 select.pool.epoll,这些都属于同步,还不属于异步 一.IO多路复用介绍 1. ...

  7. IO多路复用之select

    IO多路复用之select总结   1.基本概念 IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程.IO多路复用适用如下场合: (1)当客户处理多个描述字时(一般是交 ...

  8. 网络通信 --> IO多路复用之select、poll、epoll详解

    IO多路复用之select.poll.epoll详解      目前支持I/O多路复用的系统调用有 select,pselect,poll,epoll,I/O多路复用就是通过一种机制,一个进程可以监视 ...

  9. IO多路复用之select、poll、epoll

    本文转载自IO多路复用之select.poll.epoll 导语 IO多路复用:通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. ...

  10. python基础-11 socket,IO多路复用,select伪造多线程,select读写分离。socketserver源码分析

    Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...

随机推荐

  1. Apache Kafka - How to Load Test with JMeter

    In this article, we are going to look at how to load test Apache Kafka, a distributed streaming plat ...

  2. Java开发笔记(一百四十五)FXML布局的伸展适配

    前面介绍了FXML的基本格式及其控制器的用法,算是打通了FXML方式的编码流程.程序界面通常保持固定尺寸,不过有时也允许用户拖曳窗口大小,不拖不打紧,一拖就可能坏事.像之前的登录窗口,没拖的时候界面如 ...

  3. OI之路

    由于各种因素 学习.初赛.时间... 我的oi可能会结束, 我也不甘于放弃, 所以 综合今后的表现, 我再决定 以后我尽量写博客.

  4. 关于 Windows to go

    1. 在宿主计算器的操作系统中访问 Windows to go 的磁盘 如题,如果需要在宿主计算器的操作系统中访问 Windows to go 的U盘(移动硬盘)中的文件,只需要打开磁盘管理,“更改驱 ...

  5. 关于visual studio 2015 智能提示英文,而非中文的解决方案

    关于visual studio 2015 智能提示英文,而非中文的解决方案:   找到这个目录 C:\Program Files (x86)\Reference Assemblies\Microsof ...

  6. 常用 Git 命令汇总

    Git 命令汇总 1 Git 的一些通用术语 1.1 Git 的几个区 1.2 如何标识 Git 的某次提交 2 Git 配置 2.1 配置 2.2 读取配置 2.3 与 Beyond Compare ...

  7. Visual Studio的语法着色终于调得赏心悦目

    代码可读性瞬间大大提升.Reshaper真的强大.

  8. python numPy模块 与numpy里的数据类型、数据类型对象dtype

    学习链接:http://www.runoob.com/numpy/numpy-tutorial.html 官方链接:https://numpy.org/devdocs/user/quickstart. ...

  9. python --- Socketserver N部曲(1)

    曲一 socketserver 是为了简化服务器端开发而产生的,是一个高级的标准库.(背景介绍完毕,开始干) 一些概念 来自源码的一张图片,简洁又FengSao +------------+ | Ba ...

  10. centos从零开始安装elasticSearch

    前言:elasticSearch作为一款优秀的分布式搜索工具,被广泛用在数据搜集和整理的业务中,知名的比如有github就是采用es来精准的搜索几千万行代码,百度也大量应用es做数据爬取分析,本篇博客 ...