• I/O模型


    I/O模型

    同步、异步指提交任务方式,异步不等于阻塞,异步一般与回调联合使用

    分类:

    1. 阻塞IO
    2. 非阻塞IO
    3. IO多路复用
    4. 信号驱动IO(使用较少)
    5. 异步IO

    主要研究网络IO:

    什么功能属于IO行为?收发消息都属于网络IO行为

    阻塞IO

    server

    from socket import *
    
    server=socket(AF_INET,SOCK_STREAM)
    server.bind(('127.0.0.1',8080))
    server.listen(5)
    while True:
        conn,addr=server.accept()
        print(addr)
        while True:
            try:
                data=conn.recv(1024)
                if not data:break
                conn.sendall(data.upper())
            except ConnectionResetError:
                break
    
        conn.close()
    server.close()
    View Code

     client

    from socket import *
    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8080))
    while True:
        msg=input(">>").strip()
        if not msg:break
        client.send(msg.encode("utf-8"))
        recv=client.recv(1024)
        print(recv.decode("utf-8"))
    View Code

    非阻塞IO模型,解决IO阻塞问题,充分利用wait data时间

    server

    from socket import *
    
    server=socket(AF_INET,SOCK_STREAM)
    server.bind(('127.0.0.1',8080))
    server.listen(5)
    server.setblocking(False)#default is True
    print("starting....")
    
    rlist=[]
    while True:
        try:
            conn,addr=server.accept()
            conn.setblocking(False)
            rlist.append(conn)
        except BlockingIOError:
            del_list=[]
            for conn in rlist:
                try:
                    data=conn.recv(1024)
                    if not data:
                        del_list.append(conn)
                        continue
                    conn.send(data.upper())
                except BlockingIOError:
                    continue
                except Exception as e:
                    print(e)
                    conn.close()
                    del_list.append(conn)
            for dlist in del_list:
                rlist.remove(dlist)

    client

    from socket import *
    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8080))
    while True:
        msg=input(">>").strip()
        if not msg:break
        client.send(msg.encode("utf-8"))
        recv=client.recv(1024)
        print(recv.decode("utf-8"))

    多路复用IO模型,可以同时检测多个套接字IO

    优点:

      可以检测多个套接字,比阻塞IO快

    缺点:

      代理套接字太多后,导致很多询问无用,效率更低。linux提供pool功能。eppol可以很好解决,但是跨平台性差,windows不支持epoll

      selectors可以更加操作系统选择最优非阻塞IO

    server

    from socket import *
    import select
    server=socket(AF_INET,SOCK_STREAM)
    server.bind(('127.0.0.1',8080))
    server.listen(5)
    server.setblocking(False)#default is True
    rlist=[server]#这里为什么放server?应为也需要检测server是否有accept请求过来呀
    wlist=[]
    xliet=[]
    dlist={}#保存接收到的数据
    while True:
        rl,wl,xl=select.select(rlist,wlist,xliet,0.5)#timeout参数表示隔多久询问一次操作系统
        for sock in rl:#判断是否是rl产生数据,可能是新连接进来
            if sock==server:#有连接请求进来,需建立连接
                conn,addr=server.accept()
                print(addr)
                rlist.append(conn)#连接建立好后,放入rlist中也检测起来,即检测conn是否有数据过来
            else:#不是server肯定就是conn了,conn只有接收数据。因为rlist中只有server和conn,没其他对象
                try:
                    data=sock.recv(1024)#这里不应该直接发,也经过select来处理,所以,如下
                    if not data:#linux平台不会抛出异常,一直接收空字符串
                        sock.close()#关闭
                        rlist.remove(sock)#移除监控
                    wlist.append(sock)#放进去后就开始检测,只要缓冲区没有满,就可以发送数据
                    dlist[sock]=data#存放该conn接收到的数据,用于后面处理
                # except ConnectionResetError:#windows下,客户端断开会抛ConnectionResetError错误、
                except Exception:##检测所有异常
                    sock.close()#产生异常的连接关闭掉
                    rlist.remove(sock)#异常连接不再监控
        for sock in wl:#也可能是wl列表产生变化,所以进程迭代,wl列表中的conn只有发送数据一件事可干
            data=dlist[sock]#取出之前连接接收到的数据
            sock.send(data.upper())#对数据进行处理后发送
            wlist.remove(sock)#数据处理完后就不需要监控 该连接了,所以从监控列表中删除
            dlist.pop(sock)#也需从存储数据的字典中将该连接的数据删除掉
    server.close()

    client

    from socket import *
    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8080))
    while True:
        msg=input(">>").strip()
        if not msg:break
        client.send(msg.encode("utf-8"))
        recv=client.recv(1024)
        print(recv.decode("utf-8"))

    异步IO(Asynchronous I/O)

    后面爬虫项目介绍

  • 相关阅读:
    克服 iOS HTML5 音频的局限
    oracle__删除重复记录__三种方法及总结(转载百度文库)
    Oracle 字符集
    无法通过网页进入em
    Ubuntu 12.04(32位)安装Oracle 11g(32位)全过程以及几乎所有问题的解决办法
    正则表达式30分钟入门教程
    linux下安装jdk
    QTP相关书籍
    假的数论gcd,真的记忆化搜索(Codeforce 1070- A. Find a Number)
    搜索基础_HDU1312_dfs_递归+stack实现+bfs_queue实现
  • 原文地址:https://www.cnblogs.com/yaya625202/p/9049196.html
Copyright © 2020-2023  润新知