• day19-IO多路复用


    1、I/O多路复用指:通过一种机制,可监听多个描述符(soket对象)(文件句柄),一旦某个描述符发送编号(一般指读就绪或写就绪),能够通知程序进行相应的读写操作。

    2、I/O多路复用方式:select、poll 、epool。
    win 只支持select
    select:使用for循环,描述符最多1024个
    pool:使用for循环实现,对文件描述符没有限制,
    epoll:优化了实现方式,不在使用for循环,使用了异步的方式,效率高

    2.1 select方式工作原理:

    后面的1表示延时等待时间

    nginx在内部就是基于epoll来实现的,使用epool+select来监听用户请求

    2.2多路复用+socket实现伪并发处理示例

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import socket
    sk1 = socket.socket()
    sk1.bind(('127.0.0.1', 8001))
    sk1.listen()
    
    # sk2 = socket.socket()
    # sk2.bind(('127.0.0.1', 8002))
    # sk2.listen()
    #
    # sk3 = socket.socket()
    # sk3.bind(('127.0.0.1', 8003))
    # sk3.listen()
    
    # inputs = [sk1, sk2, sk3, ]
    inputs = [sk1, ]
    outputs = []
    message_dict = {}
    import select
    while True:
        #[sk1,sk2, ],内部自动监听sk1, sk2 两个对象, 一旦某个句柄发生变化,就能感知到
        #如果有人连接 sk1
        #r_list = [sk1, ]
        #如果有人连接sk1发生编号
        r_list, w_list, e_list = select.select(inputs, outputs, inputs, 1)
        print("正在监听的socket对象总计:%d" % len(inputs))
        print(r_list)
        for sk1_or_conn in r_list:
            #每一个连接对象
            if sk1_or_conn == sk1:
                conn, address = sk1_or_conn.accept()
                inputs.append(conn)
                message_dict[conn] = []
            else:
                #有老用户发消息了
                try:
                    data_bytes = sk1_or_conn.recv(1024)
                    # data_str = str(data_bytes, encoding='utf-8')
                    # sk1_or_conn.sendall(bytes(data_str+'好', encoding='utf-8'))
                except Exception as ex:
                    #用户终止连接
                    print(ex)
                    inputs.remove(sk1_or_conn)
                else:
                    #用户正常发送消息
                    data_str = str(data_bytes, encoding='utf-8')
                    message_dict[sk1_or_conn].append(data_str)
                    # sk1_or_conn.sendall(bytes(data_str+'好', encoding='utf-8'))
    
                    outputs.append(sk1_or_conn)
            # conn.sendall(bytes('hello',encoding='utf-8'))
            # conn.close()
    
        #w_list 仅仅保存了谁给我发过消息
        for conn in w_list:
            recv_str = message_dict[conn][0]
            del message_dict[conn][0]
            conn.sendall(bytes(recv_str+'', encoding='utf-8'))
            outputs.remove(conn)
    
        for sk1_or_conn in e_list:
            inputs.remove(sk1_or_conn)
    
    # while True:
    #     conn, address = sk.accept()
    #     while True:
    #         content_bytes = conn.recv(1024)
    #         content_str = str(content_bytes, encoding='utf-8')
    #         conn.sendall(bytes(content_str + '好', encoding='utf-8'))
    #     conn.close()
    server
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import socket
    
    obj = socket.socket()
    
    obj.connect(('127.0.0.1',8001 ))
    
    while True:
        inp = input('>>>>>')
        obj.sendall(bytes(inp,encoding='utf-8'))
        ret = str(obj.recv(1024),encoding='utf-8')
        print(ret)
    
    
    #
    # content = str(obj.recv(1024),encoding='utf-8')
    # print(content)
    obj.close()
    # #阻塞
    # print('等待中')
    # ret_bytes = obj.recv(1024)  #设置最高多接受的字节数,超过后需要等下次在接受
    # print(str(ret_bytes,encoding='utf-8'))
    # print('接受完成')
    # # obj.close()
    # while True:
    #     inp = input('请输入要发送的内容(q退出)
     >>>')
    #     if inp == 'q':
    #         obj.sendall(bytes(inp,encoding='utf-8'))
    #         break
    #     else:
    #         obj.sendall(bytes(inp,encoding='utf-8'))
    #         ret = str(obj.recv(1024),encoding='utf-8')
    #         print(ret)
    # obj.close()
    client
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import  socket
    sk1 = socket.socket()
    sk1.bind(('127.0.0.1', 8001))
    sk1.listen()
    
    sk2 = socket.socket()
    sk2.bind(('127.0.0.1', 8002))
    sk2.listen()
    
    sk3 = socket.socket()
    sk3.bind(('127.0.0.1', 8003))
    sk3.listen()
    
    inputs = [sk1, sk2, sk3, ]
    import select
    while True:
        #[sk1,sk2, ],内部自动监听sk1, sk2 两个对象, 一旦某个句柄发生变化,就能感知到
        #如果有人连接 sk1
        #r_list = [sk1]
        r_list, w_list, e_list = select.select(inputs, [], [], 1)
        for sk in r_list:
            #每一个连接对象
            conn, address = sk.accept()
            conn.sendall(bytes('hello',encoding='utf-8'))
            conn.close()
    
    # while True:
    #     conn, address = sk.accept()
    #     while True:
    #         content_bytes = conn.recv(1024)
    #         content_str = str(content_bytes, encoding='utf-8')
    #         conn.sendall(bytes(content_str + '好', encoding='utf-8'))
    #     conn.close()
    server-demo2

    2.3关于并发

    3、初始超线程

    #!/usr/bin/envpython
    #-*-coding:utf-8-*-
    importthreading
    importtime
    
    defprocess(arg):
    time.sleep(1)
    print(arg)
    
    
    #foriinrange(10):
    #process(i)
    
    foriinrange(10):
    t=threading.Thread(target=process,args=(i,))
    t.start()
    demo

    4、Soketserver原码解析

    原理图

     5、初始多线程

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import  threading
    import  time
    
    def process(arg):
        time.sleep(1)
        print(arg)
    
    
    # for i in range(10):
    #     process(i)
    
    for i in range(10):
        t = threading.Thread(target=process, args=(i,))
        t.start()
    多线程
  • 相关阅读:
    Spring Boot 2.0 + zipkin 分布式跟踪系统快速入门
    在线yaml转Properties
    Spring Boot 配置优先级顺序
    集群服务器下使用SpringBoot @Scheduled注解定时任务
    spring-boot项目在eclipse中指定配置文件启动
    org.hibernate.TransientObjectException异常
    Servlet、ServletConfig、ServletContext深入学习
    Spring中构造器、init-method、@PostConstruct、afterPropertiesSet孰先孰后,自动注入发生时间以及单例多例的区别、SSH线程安全问题
    nested exception is com.svorx.core.dao.PersistenceException
    yui压缩JS和CSS文件
  • 原文地址:https://www.cnblogs.com/workherd/p/8458530.html
Copyright © 2020-2023  润新知