• 同步与异步编程



    同步阻塞:  立即返回最终结果     
    同步不阻塞: 等待 返回最终结果     
     
    同步,异步,与 阻塞,非阻塞 不相关
    同步 异步  ——>  强调的是结果
    阻塞 非阻塞 ——> 强调的是时间,是否等待
     
     
    同步与异步的区别:调用者是否得到了想要的结果
     
    同步 一直执行到返回结果
    异步直接返回,但不是最终结果。调用者不能通过这种调用得到结果,还要通过被调用者,使用其他方式通知调用者,来拿到最终结果
     
    阻塞与非阻塞的区别在于  调用者是否在阻塞期间能做彼得事
    阻塞,调用者只能 等到出结果为止
    非阻塞, 调用者可以执行别的函数,不用一直等
     
    同步IO,异步IO,IO多路复用
    IO两个阶段:
    1,数据准备阶段
    2,内核空间复制回用户进程缓冲区阶段
     
    发送IO的时候
    内核从输入设备读写数据
    进程从内核复制数据
     
    同步IO
    同步IO模型包括,阻塞IO,非阻塞IO,IO多路复用
     
    阻塞IO
     
    进程等待(阻塞),直到读写完成(全程等待)
    read/write
     
    非阻塞IO
    进程调用read操作,如果IO设备没有准备好,立即返回ERROR,进程不阻塞,用户可以在此发起系统调用,如歌内核已经准备好,就阻塞,然后复制数据到用户空间
    第一阶段,重复检查数据是否准备好,非阻塞
    第二阶段,阻塞,等待服务端数据拷贝完毕为止
     
     
    IO多路复用:
    同时监控多个IO,有一个准备好了就不需要等了,开始处理,提高了同时处理IO的能力
    select所有平台支持
    select 作为一个监控,可以帮你看着一个进程操作是否满足条件,若满足条件,会通知用户进程
     
    以select为例,将关注的IO操作 告诉select函数并调用,进程阻塞,内核“监视”select关注的文件描述符fd,
    被关注的任何一个fd对应的IO准备好了数据,select返回,在使用read将数据复制到用户进程、
     
    异步IO:
    进程发起异步IO请求,立即返回一个状态,内核完成IO的两个阶段,内核给进程发送信号
     
    python中IO多路复用
    python的select库
    实现了select库,底层的IO多路复用模块
    开发平台的选择,根据不同操作系统自行选择支持的技术,这样做会提高IO处理的性能
     
    selectors库
    3.4版本提供足够库,高级io复用
    selectors.DefaultSelector 返回当前平台最有效,性能最高的实现
    没有实现windows下的IOCP,windows下退化为select
     
    abstractmethod register(fileobj,events,data = None)
    为selection注册一个文件对象,监视它的IO事件
     
    fileobj被监控文件对象,例如socket对象
    events事件,该文件对象必须等待的事件
    data  本例中关联的方法,监控其状态改变后的下一步操作
    将聊天软件 改写成IO多路复用的模式
    
    
     #将ChatServer改为IO多路复用的方式
    
    
     #从而不需要多线程的启动了
    import socket
    import selectors
    import threading
    import logging
    logging.basicConfig(format="%(message)s ",level=logging.INFO)
     
    class Chat_Server:
        def __init__(self,ip="127.0.0.1",port = 7888):
            self.sock = socket.socket()
            self.addr = (ip,port)
            self.event = threading.Event()
            self.selector = selectors.DefaultSelector()
     
        def start(self):
            self.sock.bind(self.addr)
            self.sock.listen()
            self.sock.setblocking(False)
            self.selector.register(self.sock,selectors.EVENT_READ,self._accept) #指向accept,说明状态后需要执行的操作,只做监控,并不执行
            threading.Thread(target=self._run).start()
     
        def _run(self):
            while not self.event.is_set():
                events = self.selector.select(1)        #将监控到的数据,传给一个容器,有容器去回调他们该做的操作
                for key,mask in events:
                    callback = key.data               #key.data 指向的 是监控状态发生改变的事件该执行的函数
                    callback(key.fileobj)               #用该函数,传入一个socket对象,达到其结果
     
     
        def _accept(self,sock:socket.socket):
            conn,client = sock.accept()
            conn.setblocking(False)
            key = self.selector.register(conn,selectors.EVENT_READ,self._recv)  ##recv,说明状态后需要执行的操作,只做监控,并不执行
     
        def _recv(self,conn:socket.socket):
            data = conn.recv(1024).decode().strip()
            logging.info(data)
            # conn.send(data.encode())
     
    e = threading.Event()
    cs = Chat_Server()
    cs.start()
     
    while not e.wait(1):
        cmd = input(">>>").strip()
        if cmd == "quit":
            cs.stop()
            e.wait(3)
            break
     
  • 相关阅读:
    责任
    人生
    有感
    冲突无处不在
    中科院玉泉路攻略——吃篇(校外)
    兄弟
    (18)[转载]:跳台阶问题
    Excel表格加下列选择框
    (转载)(c#)数据结构与算法分析 数组、向量和表
    [转载] 趣味算法:字符串反转的N种方法
  • 原文地址:https://www.cnblogs.com/spidermansam/p/8098733.html
Copyright © 2020-2023  润新知