事件驱动,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'))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值