zoukankan      html  css  js  c++  java
  • 协程异步非阻塞

    1、gevent. 在遇到io操作时会发生切换,切换gevent.joinall()中的gevent.spawn(a)去执行。

    使用非gevent封装的sleep()时会发生阻塞

    import gevent
    import time
    
    def a():
        print("begin a",time.time())
        time.sleep(1)
        print("end a ",time.time())
    
    def b():
        print("begin b",time.time())
        time.sleep(1)
        print("end b ",time.time())
    
    def c():
        print("begin c",time.time())
        time.sleep(1)
        print("end c ",time.time())
    
    
    if __name__ == "__main__":
        gevent.joinall([
            gevent.spawn(a),
            gevent.spawn(b),
            gevent.spawn(c),]
        )
    
    运行结果:
    begin a 1466328299.3592122
    end a  1466328300.3595576
    begin b 1466328300.3595576
    end b  1466328301.3598628
    begin c 1466328301.3598628
    end c  1466328302.3601925
    

    2、使用gevent.sleep(1)时是非阻塞的。但是当然这个sleep(1)睡眠1秒还是要经历的,只是a在睡眠时可以切换到b或c去执行:

    将上面的time.sleep(1)改为gevent.sleep(1)

    gevent.sleep(1)
    
    运行结果:
    begin a 1466328564.0706365
    begin b 1466328564.0891385
    begin c 1466328564.089639
    end a  1466328565.0892923
    end c  1466328565.0907917
    end b  1466328565.0907917
    

    3、在文件最开始使用from gevent import monkey;monkey.patch_all() 可以使time.sleep(1)为非阻塞。这样就不用gevent的sleep(1)了。

    4、gevent实现单线程socket允许同时多个连接同时发生数据。  也可以使用from gevent import socket,这样就不用使用monkey.patch_all()了。

    简单示例代码:

    # 服务器端
    import gevent
    import time
    import socket
    from gevent import monkey;monkey.patch_all()
    
    def server(port):
        s = socket.socket()
        s.bind(('127.0.0.1',port))
        s.listen(50)
        # s.setblocking(False)
        while True:
            conn, addr = s.accept()    # 接收客户端连接
            print("来了一个连接:",addr)
            gevent.spawn(handle_switch,conn)   # gevent.spawn()里的handle_switch()内部会非阻塞状态
    
    def handle_switch(conn):
        while True:
            try:
                data = conn.recv(1024)        # 非阻塞,并不代表会往下执行,在这里而是发生切换。
            except ConnectionResetError as e:
                print(e)
                conn.close()
                break
            conn.send(data)                   # 非阻塞
            print("recv:",data.decode())
            if not data:
                conn.close()
                print("客户端正常关闭")
                break
    if __name__ == "__main__":
        server(9001)
    
    # 客户端
    import socket
    
    s = socket.socket()
    s.connect(('127.0.0.1',9001))
    
    while True:
        data = input(">> ").strip()
        if data == "":
            continue
        if data == "q":
            s.close()
            break
        s.send(bytes(data,encoding="utf-8"))
        data = s.recv(1024)
        print("recv:",data.decode())
    

    发起两个连接:

    允许结果:

    来了一个连接: ('127.0.0.1', 55801)    # 第一个客户端连接
    recv: asd                                         
    recv: asd
    来了一个连接: ('127.0.0.1', 55804)    # 第二个客户端连接
    recv: sdfa
    recv: asdg
    recv: 1
    recv: 1
    recv: 2
    recv: 2
    recv: 1
    recv: 2
    recv:                                                # 客户端1断开连接,data为空
    客户端正常关闭                                   # 客户端1正常断开,即客户端是s.close()的
    recv: haha
    recv:                                                # 客户端2断开连接,data为空
    客户端正常关闭                                   # 客户端1正常断开,即客户端是s.close()的
    来了一个连接: ('127.0.0.1', 55820)     # 第三个客户端连接
    recv: asd
    [WinError 10054] 远程主机强迫关闭了一个现有的连接。       # 客户端3非正常连接,应该是被kill掉了进程,客户端发送rst包。
    
  • 相关阅读:
    HTML&CSS 学习网站收藏【转】
    HTML5安全:CORS(跨域资源共享)简介【转】
    SPDY以及示例
    前端开发中,对图片的优化技巧有哪些?(比如淘宝首页的图片)
    【javascript基础】之【__lookupSetter__ 跟 __lookupSetter__】
    毫秒必争,前端网页性能最佳实践【转】
    最近遇到的兼容性问题和适配问题
    备份的一些小tip
    Http2改造实践:statusText丢失问题
    vue-cli脚手架npm相关文件解读(9)config/index.js
  • 原文地址:https://www.cnblogs.com/owasp/p/5599286.html
Copyright © 2011-2022 走看看