事件驱动,IO模型

事件驱动,IO模型1.事件驱动;是一种编程方式(编程思想),与编程语言不要紧    事件之间互不影响,谁触发谁执行    <!DOCTYPE html>    <html lang="en">    <head>        <meta charset="UTF-8">        <title>Title</title>    </head>    <body>    <p onclick="func()">点我呀</p>    <script>        function func() {            alert('eric210')        }    </script>    </body>    </html>传统事件监听的方式:(占用cpu资源)    def f():        pass    while 1:        鼠标检测2.IO模型:    IO (计算机用语):I/O输入/输出(Input/Output),分为IO设备和IO接口两个部分。 在POSIX兼容的系统上,例如Linux系统 [1],    I/O操做能够有多种方式,好比DIO(Direct I/O),AIO(Asynchronous I/O,异步I/O),Memory-Mapped I/O(内存映射I/O)等,不一样    的I/O方式有不一样的实现方式和性能,在不一样的应用中能够按状况选择不一样的I/O方式。    IO多路复用:前面是用协程实现的IO阻塞自动切换,而协程的原理和在事件驱动的状况下IO的自动阻塞的切换的学名叫===》IO多路复用                socketserver,多个客户端链接,单线程下实现并发效果,就是多路复用。    同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,区别是什么,不一样的人在不一样的上下文给出的答案是不一样的,因此先限定一下本文上下    文本文讨论的背景是Linux环境下的networkIO。    (1)用户空间和内核空间:用户空间没法访问内核空间    (2)进程切换:切换过程大量消耗时间    (3)进程的阻塞    (4)文件描述    (5)缓存I/O:很是消耗资源3.Stevens在文章中比较了五种IO Mode:    (1)blocking IO(阻塞IO):blockingIO的特色就是在IO执行的两个阶段都被block了(阻塞,就是调用我(函数),我(函数)                               没有接收完数据或者没有获得结果以前,我不会返回。)        import socket        sk=socket.socket()        sk.bind()        sk.listen(3)        # sk.setblocking()#过滤阻塞IO        con,add=sk.accept()        con.recv()        con.send()        弊端:进程全程阻塞状态,什么都干不了        实例:            #server端            #author: wylkjj            #date:2019/5/20            import socket            sk = socket.socket()            address=('127.0.0.1',8080)            sk.bind(address)            sk.listen(3)            sk.setblocking(False)            import time            while 1:                try:                    conn,add=sk.accept()                    while 1:                        data=conn.recv(1024)                        print(data.decode('utf8'))                        conn.sendall(data)                        conn.close()                except Exception as e:                    print('error:',e)                    time.sleep(3)            #clinet端            #author: wylkjj            #date:2019/5/20            import socket            sk = socket.socket()            address=('127.0.0.1',8080)            sk.connect(address)            while 1:                # inp=input(">>>:")                sk.sendall('hello'.encode('utf8'))                data=sk.recv(1024)                print(data.decode('utf8'))    (2)nonblocking IO(非阻塞IO):copy状态也是阻塞的,可是其它状态不是阻塞的,例如recv()屡次发送询问(非阻塞,就是调                                    用我(函数),我(函数)当即返回,经过select通知调用者)                                    弊端:数据延迟,数据不能及时拿到    (3)IO multiplexing(IO多路复用):这个词会陌生,可是select,epoll大概会明白,有些地方称这种IO方式为event driven IO        select/epoll的好处在于单个process能够同时处理多个网络链接的IO基本原理就是select/epoll这个function会不断的轮询所        负责的全部socket,当某个socket有数据到达了,就通知用户进程        select优势:能够同时监听多个文件描述符实现并发效果。(跨平台)        epoll:大多数都用epoll,也能够同时监听多个文件描述符实现并发效果。        主权:因此IO多路复用的模型也属于同步IO    (4)signal driven IO(信号驱动IO,实际中不经常使用)    (5)asynchronous IO(异步IO):进程再也不阻塞,注:只要有一点阻塞就不是异步IO(异步,就是我调用一个功能,不须要知道该                                    功能结果,该功能有结果后通知我(回调通知)。)         synchronous IO(同步IO):除异步IO上面的都属于同步IO(同步,就是我调用一个功能,该功能没有结束前,我死等结果。)4. 注意区别:他们针对的对象是不一样的    同步IO和异步IO的区别就在于:数据拷贝的时候进程是否阻塞    阻塞IO和非阻塞IO的区别就在于:应用程序的调用是否当即返回5.IO multiplexing(IO多路复用):select,epoll    select:r,w,e=select.select([sk1,sk2],[],[],5),5表示监听5秒,5秒一打印    select实例1:(select是一种水平触发)            #author: wylkjj            #date:2019/5/20            #server端            import socket,select            sk1 = socket.socket()            address1=('127.0.0.1',8080)            sk1.bind(address1)            sk1.listen(3)            sk2=socket.socket()            address2=('127.0.0.1',8081)            sk2.bind(address2)            sk2.listen(3)            while True:                r,w,e=select.select([sk1,sk2],[],[])                print('rrr')                for obj in r:                    conn,addr=obj.accept()#conn会变,临时分配,可是链接的socket对象是同样的                    print('conn',conn)                    print("hellow")                print('r:>>',r)            #author: wylkjj            #date:2019/5/20            #clinet1端            import socket            sk = socket.socket()            address=('127.0.0.1',8080)            sk.connect(address)            while 1:                data=sk.recv(1024)                print(data.decode('utf8'))                inp=input(">>>:")                sk.sendall(inp.encode('utf8'))            #author: wylkjj            #date:2019/5/20            #clinet2端            import socket            sk = socket.socket()            address=('127.0.0.1',8081)            sk.connect(address)            while 1:                data=sk.recv(1024)                print(data.decode('utf8'))                inp=input(">>>:")                sk.sendall(inp.encode('utf8'))        实例2:clinet同上同样            #author: wylkjj            #date:2019/5/20            #server端            import socket,select            sk1 = socket.socket()            address1=('127.0.0.1',8080)            sk1.bind(address1)            sk1.listen(3)            sk2=socket.socket()            address2=('127.0.0.1',8081)            sk2.bind(address2)            sk2.listen(3)            while True:                r,w,e=select.select([sk1,sk2],[],[])                # print('rrr')                for obj in r:                    conn,addr=obj.accept()#conn会变,临时分配,可是链接的socket对象是同样的                    print('conn',conn)                    print("hellow")                print('r:>>',r)    epoll既能够采用水平触发,也能够采用边缘触发        水平触发:也就是只有高电平(1)或低电平(0)时才触发通知,只要再这两种状态就能获得新通知,只要有数据可读(描述符                  就绪)那么水平触发的epoll就当即返回        边缘触发:只有电平发生变化(高电平到低电平,或者低电平到高电平)的时候才出发通知,即便有数据可读,可是没有新的IO                  活动到来,epoll也不会当即返回。6.IO多路复用的并发聊天:    互动聊天:        #author: wylkjj        #date:2019/5/20        #模拟并发效果        #server端        import socket        import select        sk = socket.socket()        address=('127.0.0.1',8800)        sk.bind(address)        sk.listen(3)        inp=[sk,]        while 1:            inputs, outputs, errors = select.select(inp,[],[],)            for obj in inputs:                if obj==sk:                    conn,addr=sk.accept()                    print(conn)                    inp.append(conn)                else:                    data=obj.recv(1024)                    print(data.decode('utf8'))                    Inputs=input('回答%s>>>'%inp.index(obj))                    obj.sendall(Inputs.encode('utf8'))        #author: wylkjj        #date:2019/5/20        #clinet端        import socket,time        sk = socket.socket()        address=('127.0.0.1',8800)        sk.connect(address)        while 1:            inp=input(">>>:")            sk.sendall(inp.encode('utf8'))            data = sk.recv(1024)            print(data.decode('utf8'))        #author: wylkjj        #date:2019/5/20        #clinet端        import socket,time        sk = socket.socket()        address=('127.0.0.1',8800)        sk.connect(address)        while 1:            inp=input(">>>:")            sk.sendall(inp.encode('utf8'))            data = sk.recv(1024)            print(data.decode('utf8'))
相关文章
相关标签/搜索