zoukankan      html  css  js  c++  java
  • 并发编程---IO模型

    IO模型

    任务的提交方式有两种:

    • 同步:应用程序提交完任务,等待结果结果,之后在执行下一个任务
    • 异步:应用程序提交完任务,继续执行不等待结果,任务执行完,会自动出发异步中的会带哦函数

    同步不等于阻塞:

    • 同步:提交任务完,不管任务有没有遇到阻塞,只等待接收结果,任务运行完,才接着往下走
    • 阻塞:提交任务的时候遇到IO,没有处理的话,操作系统就会抢走CPU。解决方法:使用gevent,检测到IO的时候,就切换到其他任务

    IO模型的主要分类:

    • 阻塞IO           blocking IO
    • 非阻塞IO       nonblocking IO
    • IO多路复用   IO multiplexing
    • 信号驱动IO   signal driven IO 
    • 异步IO          asynchronous IO

    遇到IO会阻塞:卡在原地; 网络IO:原地阻塞

    1.server端什么样得操作属于IO行为    

    • 服务端的accept,recv,send,
    • 其中accept,recv会感觉明显的等,
    • send 不会明显等,但也是IO行为

    2.为什么IO行为会让有在原地等待的效果

          由于server在recv的时候 会有一个等待的时间,就是等待操作系统缓存中存在数据,才copy到用程序当中

    阻塞IO

    import socket
    from threading import Thread
    
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.bind(('127.0.0.1',8080))
    server.listen(5)
    
    def communicate():
        while True:
            try:
                data = conn.recv(1024)
                print('接收的数据:' ,data)
                conn.send(data.upper())
            except ConnectionResetError:
                break
        conn.close()
    
    print('setting...')
    while True:
        print('settings')
        conn,client_addr = server.accept() # io阻塞,操作系统拿走了cpu
        print(client_addr)
    
        t = Thread(target=communicate,args=(conn,))
        t.start()
    
    server.close()
    服务端
    import socket
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    client.connect(('127.0.0.1',8080))
    
    while True:
        cmd = input('>>:').strip()
        if not cmd:continue
        client.send(cmd.encode('utf-8'))
        data = client.recv(1024)
        print(data)
    phone.close()
    客户端

    非阻塞IO

    应用程序自己检测io,遇到io就切给其他的任务,这样可以使单线程的效率大大提高

    存在的问题:

    • cpu在做其他的事情时候,传来了数据,不会立即响应
    • 服务端没有任何的阻塞,就是死循环,cpu会一直的运转,进程处于就绪状态,这样大量占用cpu,让应用程序一直向操作系统询问数据好没好,在做着无用功

    多路复用IO

    阻塞io: 有wait()等待过程,copy过程,

    多路复用io: 比阻塞io多了一个select过程,这个过程可以作为中介,询问操作系统有没有数据

    • 缺点:只有一个套接字的时候比阻塞io性能低,当监测多个套接字的时候,循环慢,列表数据多的话,效率低
    • 优点:多个套接字的时候,可以交给select处理,比阻塞io性能高

    elect :列表循环 效率低

    poll :可接收得列表数据多 效率也不高

    epoll :效率最高,通过异步操作 每个套接字身上绑定个回调函数,谁好了谁触发回调,(就不用去遍历了 效率低)

    epoll:  windows 没有 ;linux 有

    selectors: 模块 自动根据操作系统选择

    import socket
    import select
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.bind(('127.0.0.1',8080))
    server.listen(5)
    server.setblocking(False)
    print('settings')
    
    rlist=[server,] #存收的套接字,有两种:conn        ,server
    wlist=[] #存发的套接字
    wdata={}
    
    while True:
        rl,wl,xl = select.select(rlist,wlist,[],0.5) #去向操作系统问套接字准备好没有,异常列表[] m每隔0.5秒问一次
        print('rl',rl)
        print('wl',wl)
    
        for sock in rl:
            if sock == server:
                conn,addr = sock.accept()
                rlist.append(conn)
            else:
                try: #适用于windows系统
                    data = sock.recv(1024)
                    if not data: #适用于linux系统,会一直收空
                        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)
    
    server.close()
    服务端
    import socket
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    client.connect(('127.0.0.1',8080))
    
    while True:
        cmd = input('>>:').strip()
        if not cmd:continue
        client.send(cmd.encode('utf-8'))
        data = client.recv(1024)
        print(data.decode('utf-8'))
    
    phone.close()
    客户端
  • 相关阅读:
    hdu3457(有向图的dp问题)
    nyoj16矩形嵌套(第一道dp关于dag的题目)
    noj1475(递推题)统计多少个1
    hdu1331(记忆化搜索)
    hdu1142(dj+记忆化搜索)
    hdu1978(记忆化搜索)
    用广搜实现的spfa
    hdu1428(记忆化搜索)
    hdu1078(记忆化搜索)
    poj3261(后缀数组)
  • 原文地址:https://www.cnblogs.com/Mryang123/p/8948098.html
Copyright © 2011-2022 走看看