開始 ----> 代碼塊A ---->代碼塊B ---->代碼塊C 。。。。。。 結束
每一個代碼塊都有各自實現的功能,按照條件語句順序判斷執行,每一次運行順序或許都不一樣,它的控制流程是由獲取的數據所和判斷語句所決定的。編程
開始 ----> 初始化 ----> 等待
事件驅動器啓動後,在等待事件觸發,而後作出相應的程序執行效果。觸發事件包括:輸入信息、鼠標、敲擊鍵盤、內部定時器等服務器
一個進程在執行某個任務時,另一個進程必須等待其執行完畢,才能繼續執行網絡
所謂同步,就是在發出一個功能調用時,在沒有獲得結果以前,該調用就不會返回。按照這個定義, 其實絕大多數函數都是同步調用。可是通常而言,咱們在說同步、異步的時候, 特指那些須要其餘部件協做或者須要必定時間完成的任務。
當一個異步功能調用發出後,調用者不能馬上獲得結果多線程
當該異步功能完成後,經過狀態、通知或回調來通知調用者。若是異步功能用狀態來通知, 那麼調用者就須要每隔必定時間檢查一次,效率就很低(有些初學多線程編程的人,總喜歡用一個循環去檢查某個變量的值,這實際上是一 種很嚴重的錯誤)。 若是是使用通知的方式,效率則很高,由於異步功能幾乎不須要作額外的操做。至於回調函數,其實和通知沒太多區別。
調用結果返回以前,當前線程會被掛起併發
函數只有在獲得結果以後纔會 將阻塞的線程激活。有人也許會把阻塞調用和同步調用等同起來,實際上他是不一樣的。對於同步調用來講不少時候當前線程仍是激活的,只是從邏輯上當前函數沒有返回而已。
和阻塞IO對立app
在不能馬上獲得結果以前也會馬上返回,同時該函數不會阻塞當前線程
只有高電平(1)或低電平(0)的時候才觸發通知,只要在這兩種狀態就能獲得通知,只要有數據可讀,那麼水平觸發的epoll就當即返回異步
只有電平發生變化(高電平到低電平,或者低電平到高電平)的時候才觸發通知,有數據可讀,但沒有新的IO活動到來,epoll不會當即返回socket
select優缺點對比async
select:輪詢方式,遍歷每一個監聽對象是否有數據變更,效率較低函數
epoll:主動響應,主動提交數據變更提高效率
服務端
# -*- coding:utf8 -*- import socket,select test = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #定義socket通訊方式和通訊協議。socket.AF_INET基於網絡通訊,socket.SOCK_STREAM基於TCP協議 test.bind(('127.0.0.1',8000)) # 定義通訊ID test.listen(5) # 定義最大通訊監聽數 inputs = [test,] #定義監聽socket對象的列表 while True: r,w,e = select.select(inputs,[],[],5) # select監聽 socket 對象,後跟時間單位爲秒 for obj in r: # 遍歷監聽對象列表 if obj == test: # 判斷監聽對象是否和上次遍歷同樣 conn,addr = obj.accept() # 被動接收套接字創建的鏈接 print('accepted',conn,'from',addr) inputs.append(conn) # 添加新socket對象到列表 else: msg = obj.recv(1024) # 定義接收字節信息 print('客戶端發送的消息是:', msg) obj.send(msg.upper()) # 定義發送消息 print("服務監聽中...")
服務監聽中... 客戶端發送的消息是: b'abc' 服務監聽中... 客戶端發送的消息是: b'aaa' 服務監聽中...
客戶端
# -*- coding:utf8 -*- import socket test = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #定義socket通訊方式和通訊協議。socket.AF_INET基於網絡通訊,socket.SOCK_STREAM基於TCP協議 test.connect(('127.0.0.1',8000)) #定義通訊ID,服務器的地址和端口 while True: inp = input(">>>").strip() #用戶輸入發送內容 test.sendall(inp.encode('utf-8')) #定義發送內容 data = test.recv(1024) #定義接收字節信息 print('收到服務端的發來的消息是:',data)
>>>abc 收到服務端的發來的消息是: b'ABC' >>>aaa 收到服務端的發來的消息是: b'AAA' >>>
服務端
#-*- coding:utf-8 -*- import selectors,socket sel = selectors.DefaultSelector() # 操做系統自識別合適的IO多路複用方式 def accept(sock,mask): conn,addr = sock.accept() # 被動接收套接字創建的鏈接 conn.setblocking(False) # 設置非阻塞 sel.register(conn,selectors.EVENT_READ,read) # conn 和 read 綁定,socket對象有活動調用accept方法 def read(conn,mask): try: # 異常代碼檢測防止某個客戶端斷開鏈接致使服務終止 data = conn.recv(1024) # 接收數據 if not data: # 判斷是否接收到數據 raise Exception conn.send(data.upper()) # 接收到數據並返回數據 except Exception as e: # 萬能異常 sel.unregister(conn) # 沒有接收到數據,解除conn綁定的函數 conn.close() # 關閉鏈接 sock = socket.socket() # 建立socket對象 sock.bind(('127.0.0.1',8000)) # 定義通訊ID綁定對象 sock.listen(100) # 定義最大通訊監聽數 sock.setblocking(False) # 設置非阻塞 sel.register(sock,selectors.EVENT_READ,accept) # socket 和 accept 綁定,socket對象有活動調用accept方法 print("服務運行中....") while True: events = sel.select() # 監聽socket對象 for key,mask in events: # 遍歷events對象列表 callback = key.data # 觸發socket綁定的函數accept callback(key.fileobj,mask) # 監聽到的有相應的socket對象
服務運行中....
客戶端
# -*- coding:utf8 -*- import socket test = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #定義socket通訊方式和通訊協議。socket.AF_INET基於網絡通訊,socket.SOCK_STREAM基於TCP協議 test.connect(('127.0.0.1',8000)) #定義通訊ID,服務器的地址和端口 while True: inp = input(">>>").strip() #用戶輸入發送內容 test.sendall(inp.encode('utf-8')) #定義發送內容 data = test.recv(1024) #定義接收字節信息 print('收到服務端的發來的消息是:',data)
>>>abc 收到服務端的發來的消息是: b'ABC' >>>