事件驅動,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'))
相關文章
相關標籤/搜索