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. [转帖]Java Netty简介

    Java Netty简介 https://www.cnblogs.com/ghj1976/p/3779820.html Posted on 2014-06-10 13:41 蝈蝈俊 阅读(2992) ...

  2. servlet规范--Servlet 规范其实就是对 HTTP 协议做面向对象的封装

    Servlet规范 一个最基本的 Java Web 项目所需的 jar 包只需要一个 servlet-api.jar ,这个 jar 包中的类大部分都是接口,还有一些工具类,共有 2 个包,分别是 j ...

  3. 认清楚服务器的真正身份--深入ARP工作原理

    我们知道IP地址是ISP分配给我们的,IP不能作为服务器的唯一的身份,那么服务器真正的身份是什么呢?MAC IP地址直接的通信在底层要转换到MAC直接的通信,那他们如何通信的呢? 1.简介 出场人物: ...

  4. 使用IDEA创建maven父子工程项目

    http://www.pianshen.com/article/3070289153/ 第一步: 打开IDEA,点击create new project,如果没有弹出如下界面,就先将打开的项目关闭,然 ...

  5. 阿里云RDS数据库sql server 导入数据并添加作业小结

    在阿里云购买ECS服务器和RDS数据库时,要注意网络类型要一致,最好都是VPC,否则ECS不能在内网访问RDS,只能从外网访问:在RDS控制台左侧,数据库安全性的IP白名单中添加ECS外网IP:在数据 ...

  6. Python基础之datetime、sys模块

    1.datetime模块 1)datetime.datetime.now(),返回各当前时间.日期类型. datetime.datetime.now(),返回当前日期. import datetime ...

  7. 通过Nginx为网站配置二级域名

    目录 配置域名解析 配置Nginx 重启Nginx 补充 需求:服务器上面运行多个项目:实现每个二级域名访问对应项目: 服务器:阿里云服务器:域名:阿里云注册: 配置域名解析 即配置DNS解析.一定要 ...

  8. MFC中窗口重绘

    搬家于CSDN 2015-05-14 MFC提供了三个函数用于窗口重绘 InvalidateRect(&Rect) Invalidate() UpdateWindow() 当需要更新或者重绘窗 ...

  9. Linux中Nginx中添加自签证书TLS

    创建自签证书TLS openssl req \ -newkey rsa: \ -x509 \ -nodes \ -keyout test.com.key \ -new \ -out test.com. ...

  10. Hive安装部署与配置

    Hive安装部署与配置 1.1 Hive安装地址 1)Hive官网地址: http://hive.apache.org/ 2)文档查看地址: https://cwiki.apache.org/conf ...