zoukankan      html  css  js  c++  java
  • Python之io概念

    """
    同步,异步:
    强调结果,调用者最终是否得到想要的结构
    阻塞非阻塞:
    强调时间是否等待
    
    io二个阶段
    1.数据准备阶段
    2.内核空间复制回用户空间缓冲区阶段
    
    发生io时候
    1.内核从输入设备读,写数据
    2.进程从内核复制数据
    
    io模型
    1.同步io包括阻塞io,非阻塞io,io多路复用
        阻塞io:进程等待(阻塞),直到读写完成
        非阻塞io:
            进程调用read操作,如果io没有准备好,立即返回error,进程不阻塞
            用户可以再次发起系统调用,内核准备好,就阻塞,复制数据到用户空间
        io多路复用:
            就是同时监控多个io,有一个准备好,就不需要等待了开始处理,提高了同时处理io的功能
            select所以的平台都支持,poll是对其的升级,epoll对poll的曾强增加回调机制,select最多监控
            1024个fd,select轮询的方式,效率低下
            epoll,fd没有上限,并且是回调机制,不需要遍历,效率高
    2.异步io
    进程发起异步io请求,立即返回,内核完成io的二个阶段,内核给进程发一个信号
    linix aio的系统调用
    """
    
    '''
    abstractmethod register(fileobj,events,data=None)
    为selector注册一个文件对象,监视他的io事件
    fileobj被监视文件对象,例如socket
    events事件,该文件对象必须等待的事件
    data可选的与此文件对象相关联的不透明数据,例如关联用来存储每个客户端的会话id
    event_read 可读0b01内核准备好输入输出设备,可以开始读了
    event_write可写0b10内核准备好了,可以写了
    '''  

    io多路复用

    import selectors
    import socket
    #在winodws上使用的是select,移植到linux就是epoll
    #recv,send就是io操作
    sel = selectors.DefaultSelector()
    
    def accept(sock, mask):
        conn, addr = sock.accept()  # Should be ready
        print('accepted', conn, 'from', addr)
        conn.setblocking(False)
        sel.register(conn, selectors.EVENT_READ, read) #产生new_socket的时候调用read函数
    
    def read(conn, mask):
        data = conn.recv(1000)  # Should be ready
        if data:
            print('echoing', repr(data), 'to', conn)
            conn.send(data)  # Hope it won't block
        else:
            print('closing', conn)
            sel.unregister(conn)
            conn.close()
    
    sock = socket.socket()   #产生fileobj
    sock.bind(('localhost', 1234))
    sock.listen(100)
    sock.setblocking(False) #非阻塞,要求
    sel.register(sock, selectors.EVENT_READ, accept) ##参数fileobj,events,data=None(回调函数,或者数据)
    '''
    产生socket,就是有连接请求,传给回调函数执行 sock,selectors.EVENT_READ说明socket和读就绪后执行accept
    '''
    # key = sel.register(sock, selectors.EVENT_READ, accept) key有四个属性,fileobj,fd,events,data
    
    
    while True:
        events = sel.select() #阻塞,直到events(读,写)
        for key, mask in events:  #key有四个属性,fileobj,fd,envets,data(accept,read等回调函数)
            callback = key.data    #当socket接入时,key.data = accept
            callback(key.fileobj, mask)  #accept(key.fileobj,mask) ,key.ffileoj就是sock
    import socket
    import threading
    import datetime
    import selectors
    
    class ChatServer:
        def __init__(self,ip='127.0.0.1',port=9999):
            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)
            threading.Thread(target=self.select,daemon=True).start()
    
        def select(self):
            while not self.event.is_set():
                events = self.selector.select()
                for key,mask in events:
                    callback = key.data
                    callback(key.fileobj)
    
        def accept(self,sock:socket.socket):
            conn,addr = sock.accept()
            conn.setblocking(False)
            self.selector.register(conn,selectors.EVENT_READ,self.receive)
    
        def receive(self,sock:socket.socket):
            data = sock.recv(1024)
            if data ==b"":
                self.selector.unregister()
                self.sock.close()
                return
            msg = '{}:{}
    {}
    '.format(*sock.getpeername(),data.decode())
            for key in self.selector.get_map().values():
                if key.data==self.receive: #排除self.accept
                    key.fileobj.send(msg)
        def stop(self):
            self.event.set()
            fobjs = []
            for fd,key in self.selector.get_map().items():
                fobjs.append(key.fileobj)
            for fobj in fobjs:
                self.selector.unregister(fobj)
                fobj.close()
            self.selector.close()
    
    def main():
        cs  = ChatServer()
        cs.start()
        while True:
            cmd = input(">>>")
            if cmd == 'quit':
                cs.stop()
                break
    if __name__ == '__main__':
        main()
    本文为原创文章,转载请标明出处
  • 相关阅读:
    OI 复赛注意事项整理
    U138415 堆箱子 | 扩展欧几里得 扩欧
    扩欧-扩展欧几里得 | 数论学习笔记
    U138097 小鱼吃大鱼 埃氏筛
    牛客1029A 袜子分配
    U137971 公司搬迁
    初赛知识点整理
    SQL注入技术
    写出易于调试的SQL
    dos命令大全
  • 原文地址:https://www.cnblogs.com/harden13/p/9203857.html
Copyright © 2011-2022 走看看