• Python 之IO模型


    阻塞IO模型:以前写的套接字通信都是阻塞型的。通过并发提高效率

    非阻塞IO模型:

    from socket import *
    
    # 并不推荐使用,一是消耗cpu资源,二是会响应延迟
    server = socket(AF_INET, SOCK_STREAM)
    server.bind(('127.0.0.1',8087))
    server.listen(5)
    server.setblocking(False)
    conn_list = []
    wlist = []
    while True:   # 死循环,消耗cpu大
        try:
            conn,addr = server.accept() #等待连接
            conn_list.append(conn)
            print(conn_list)
        except BlockingIOError:   # 如果没有客户端发送连接请求,干通信活
            del_list=[]
            # 收消息
            for conn in conn_list:  # 如果有超多客户端时,可能会服务延迟
                try:
                    data = conn.recv(1024)
                    if not data:
                        del_list.append(conn)
                        continue
                    wlist.append((conn,data.upper()))
                except BlockingIOError:
                    continue
                except Exception:
                    conn.close()
                    del_list.append(conn)
            #发消息
            del_wlist = []
            for item in wlist:
                try:
                    conn = item[0]
                    data = item[1]
                    conn.send(data)
                    del_list.append(item)
                except BlockingIOError:
                    pass
            for item in del_wlist:
                wlist.remove(item)
            for conn in del_list:
                conn_list.remove(conn)
    server.close()

    多路复用IO模型,又叫事件驱动IO,使用select模块或poll(epoll)实现。

    select模块优点:只用单线程(进程)执行,占用资源少,同时能为多客户端提供服务。

    缺点:select()接口并不是实现‘事件驱动’的最好选择,因为当套接字较多时,需要消耗大量时间去轮询。很多操作系统提供了更为高效的接口,如

    linux提供了epoll,BSD提供了kqueue,Solaris提供了/dev/poll。。。

    epoll更被推荐(采用异步方式,有回调机制,不需轮询),遗憾的是各操作系统提供的epoll接口差异很大。

    selector模块能根据平台选择IO多路复用的不同机制

    import socket
    import select
    server = socket.socket()
    server.bind(('127.0.0.1', 8800))
    server.listen(5)
    # sock.setblocking(False)
    rlist = [server, ]  # 有新客户端连接时,sock变化
    wlist = []
    wdata = {}
    while 1:
        rl, wl, el=select.select(rlist, wlist, [], 0.5) # 每过0.5s监听有变化的套接字(server或conn)
        print('rl', rl)
        print('wl', wl)
        for sock in rl:
            if sock == server:
                conn,addr = sock.accept() # 客户端发消息时,conn变化
                rlist.append(conn)  # 有变化的conn加入rlist
                print('server working...')
            else:
                try:
                    data = sock.recv(1024)
                    # linux上
                    if not data:
                        sock.close()
                        rlist.remove(sock)
                        continue
                    wlist.append(sock)
                    wdata[sock]=data.upper()
                except Exception:
                    sock.close()
                    rlist.remove(sock)
        for sock in wl:
            data = wdata[sock]
            sock.send(data)
            wlist.remove(sock)
            wdata.pop(sock)

    异步IO模型

  • 相关阅读:
    priority of uncertainty
    0523
    6.  Design Partition Guidelines for ThirdParty IP Delivery
    0604
    the categories of constraints
    priority of setup/hold
    SECTION 4: THE TIMEQUEST GUI
    tiny mistake made confusing issues
    fgetcsv 读取csv文件出现问题解决办法
    安卓笔记之配置第一个程序
  • 原文地址:https://www.cnblogs.com/stin/p/8549811.html
Copyright © 2020-2023  润新知