IO多路复用

Posted zhangchen-sx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IO多路复用相关的知识,希望对你有一定的参考价值。

#

技术图片
IO多路复用
操作系统提供给你的
对于你的程序来说 : 是一个代理
帮助你监听所有的通信对象,是否有数据来到操作系统中
一旦有 就通知你
你再根据通知来接收相应的数据
你不需要一直循环着问每一个对象是否有信息来,而是阻塞等待,任意一个对象有信息来,我就接收
IO多路复用
技术图片
io多路复用有好几种机制 : select poll epoll
多个io对象,多个conn,sk
一个conn占着一条网络连接的路
多个conn占着多条路
多个conn复用同一个线程的操作
机制
技术图片
from socket import *
import select
s=socket(AF_INET,SOCK_STREAM) #允许端口重用
s.bind((127.0.0.1,8081))
s.listen(5)
s.setblocking(False) #设置socket的接口为非阻塞
read_l=[s,]
while True:
    r_l,w_l,x_l=select.select(read_l,[],[]) #监听对象的读事件
    print(r_l,read_l)
    for ready_obj in r_l: #
        if ready_obj == s: #sk
            conn,addr=ready_obj.accept() #此时的ready_obj等于s
            read_l.append(conn) #链接
        else:
            try:
                data=ready_obj.recv(1024) #此时的ready_obj等于conn
                if not data: #主动断开链接
                    ready_obj.close() #关掉链接
                    read_l.remove(ready_obj) #删除这个conn
                    continue
                ready_obj.send(data.upper()) #信息不为空 大写处理
            except ConnectionResetError: #操作系统差异报警
                ready_obj.close() #关闭连接
                read_l.remove(ready_obj) #删除
select 所有操作系统都有 轮询机制 监听对象多越来越慢/个数有限
技术图片
vvvv
poll 轮询 优化底层数据结构
技术图片
vvv
epoll 不使用轮询 linux 回调函数机制 不受个数影响

# 异步IO    就像快递直接放你座位上

技术图片
vvv
C语言能写 asyncio Python支持异步

# selectors 模块

技术图片
#服务端
from socket import *
import selectors

sel=selectors.DefaultSelector()
def accept(server_fileobj,mask):
    conn,addr=server_fileobj.accept()
    sel.register(conn,selectors.EVENT_READ,read)

def read(conn,mask):
    try:
        data=conn.recv(1024)
        if not data:
            print(closing,conn)
            sel.unregister(conn)
            conn.close()
            return
        conn.send(data.upper()+b_SB)
    except Exception:
        print(closing, conn)
        sel.unregister(conn)
        conn.close()



server_fileobj=socket(AF_INET,SOCK_STREAM)
server_fileobj.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
server_fileobj.bind((127.0.0.1,8088))
server_fileobj.listen(5)
server_fileobj.setblocking(False) #设置socket的接口为非阻塞
sel.register(server_fileobj,selectors.EVENT_READ,accept) #相当于网select的读列表里append了一个文件句柄server_fileobj,并且绑定了一个回调函数accept

while True:
    events=sel.select() #检测所有的fileobj,是否有完成wait data的
    for sel_obj,mask in events:
        callback=sel_obj.data #callback=accpet
        callback(sel_obj.fileobj,mask) #accpet(server_fileobj,1)

#客户端
from socket import *
c=socket(AF_INET,SOCK_STREAM)
c.connect((127.0.0.1,8088))

while True:
    msg=input(>>: )
    if not msg:continue
    c.send(msg.encode(utf-8))
    data=c.recv(1024)
    print(data.decode(utf-8))
使用
socketserver
selectors模块 + threading模块实现的

 

以上是关于IO多路复用的主要内容,如果未能解决你的问题,请参考以下文章

你管这破玩意叫 IO 多路复用?

多路转接(IO复用)接口介绍

多路复用io接口-epoll

IO多路复用 -- selectpollepoll实现TCP反射程序

IO多路复用

经典5种IO模型 | IO多路复用