zoukankan      html  css  js  c++  java
  • IO模型

    所需知识

    阻塞

    • 线程的运行状态:运行 --> 阻塞 --> 就绪 --> 运行
    • 影响效率

    非阻塞

    • 线程的运行状态:运行 --> 就绪 --> 运行

    同步

    • 提交一个任务,等待他执行完毕
    • 只有提交的任务执行完毕才能执行其他操作
    • 影响效率

    异步

    • 只管提交,不等待他执行完毕
    • 可以直接进行其他操作

    IO步骤

    1. 数据等待阶段
    2. 从内核拷贝到进程阶段

    非阻塞IO模型

    • 进行recv、recvfrom、accept等操作时不会阻塞,可以直接进行其他操作
    • 请求数据时,没有数据不阻塞,但是会返回error信息
    • 请求数据时,有数据是直接copy到应用程序
    • 不推荐使用,轮询会大量占用CPU

    非阻塞IO模型实现socket并发

    server

    import socket
    
    sk = socket.socket()
    sk.bind(("127.0.0.1",9000))
    sk.setblocking(False)# 设置socket为非阻塞模式
    sk.listen()
    conn_l = []# 用于存储conn
    del_l = []# 用于存储已经断开连接需要删除的连接
    while True:
        try:
            conn,addr = sk.accept()# 不阻塞,但是没有连接会报错
            conn_l.append(conn)# 将连接添加到用于统一管理的conn_l中
        except BlockingIOError:
            try:
                for conn in conn_l:# 利用了列表为空是for不执行的原理
                    msg = conn.recv(1024)# 不阻塞,但是没有数据会报错
                    if msg == b"":# 返回的内容为空则说明连接已经断开
                        del_l.append(conn)# 添加到待删除的列表中
                        continue
    
                    print(msg)
                    conn.send(b"bye")
            except BlockingIOError:pass
            for i in del_l:
                conn_l.remove(i)# 删除已经断开的连接
            del_l.clear()# 清空存储已经断开的连接的列表
    

    client

    import socket
    import threading
    
    def func():
        sk = socket.socket()
        sk.connect(("127.0.0.1",9000))
        sk.send(b"hello")
        print(sk.recv(1024))
        sk.close()
    
    
    for i in range(20):
        # 使用多线程来模拟多个客户端连接服务器
        t = threading.Thread(target=func)
        t.start()
    

    IO多路复用模型

    • IO多路复用是系统提供的
    • 相当于一个代理,这个代理可以监听多个对象的状态,当有对象接收到信息是返回一个状态给应用程序
    • 可以解决非阻塞IO高CPU占用的问题

    IO多路复用实现socket并发

    server

    import select
    import socket
    
    sk = socket.socket()
    sk.bind(("127.0.0.1",8080))
    sk.setblocking(False)
    sk.listen()
    read_list = [sk]
    while True:
        r_list,w_list,x_list = select.select(read_list,[],[])
        for i in r_list:
            if i is sk:
                conn,addr = i.accept()
                read_list.append(conn)
            else:
                ret = i.recv(1024)
                if ret == b"":
                    i.close()
                    read_list.remove(i)
                    continue
                print(ret)
                i.send(b"bye")
    

    client

    import socket
    import threading
    
    def func():
        sk = socket.socket()
        sk.connect(("127.0.0.1",8080))
        sk.send(b"hello")
        print(sk.recv(1024))
        sk.close()
    
    
    for i in range(20):
        # 使用多线程来模拟多个客户端连接服务器
        t = threading.Thread(target=func)
        t.start()
    
  • 相关阅读:
    Java内部类与异常类
    Java 继承和接口
    134. 加油站
    P1567 统计天数
    P2141 珠心算测验
    P1428 小鱼比可爱
    P1427 小鱼的数字游戏
    python中使用xlrd、xlwt操作excel表格详解
    同步机制
    CSS学习
  • 原文地址:https://www.cnblogs.com/changjiangwei/p/11879204.html
Copyright © 2011-2022 走看看