• 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模块实现的
  • 相关阅读:
    js正则验证邮箱格式
    PHP面向对象简易验证码类
    php 中 instanceof 操作符
    防止SQL注入
    通过实例详细讲解PHP垃圾回收机制
    PHP实现上传视频的功能
    二维数组分组
    时间戳转换为几分钟、几小时、几天、几周、几月、几年前
    自定义接口错误响应格式
    laravel写crontab定时任务(发送邮件)和laravel crontab不执行的问题
  • 原文地址:https://www.cnblogs.com/zhangchen-sx/p/11037372.html
Copyright © 2020-2023  润新知