標籤:初始 decode 就刪除 檢測 %s add 準備 理解 優勢
多工分析執行個體:服務端、用戶端
#服務端配置from socket import *import timeimport selectserver = socket(AF_INET, SOCK_STREAM)server.bind((‘127.0.0.1‘,8080))server.listen(5)server.setblocking(False)‘‘‘select/epoll的優勢並不是對於單個串連能處理得更快,而是在於能處理更多的串連。當任何一個socket中的資料準備好了,select就會返回,會從作業系統將資料拷貝到應用程式中1.select.select(read_list,write_list,[],5)是由應用程式發起的,發送給作業系統,讓作業系統去找有資料的通訊端socket 5:可以不用寫,意思是5秒如果有資料連線進來會執行,如果沒有回執行下一行代碼(不用寫是因為如果沒資料執行下面的也沒意義, 能執行下面的代碼,肯定是上面有資料過來已經成功建立了串連) 重點:是沒有資料過來才阻塞 有資料過來會一直運行,不會阻塞 2.非同步IO: 發送之後不用管,會自動把結果發給你,發一個給作業系統就不用管了(用於爬蟲,效率最高) ‘‘‘data_dic={} #設定一個空字典,目的是用於將conn:data 一一綁定read_list=[server,] #放和收訊息有關的通訊端 conn.recv() server.accept(),是被檢測的一些通訊端write_list=[] #send寫資料,存放建立好的一些通訊端服務端print(‘start....‘)while True: #select執行的返回結果是維護的列表裡面,哪個有資料過來了 rl,wl,xl=select.select(read_list,write_list,[]) #這裡select在指定的時間段內不停的去問作業系統要資料,如果沒有資料就會執行下面一行代碼 print(read_list) #read_list=[server,conn1,conn2,conn3,conn4] print(rl,len(rl)) #重點理解:上面迴圈每次得到r1只時包換作業系統詢問到的有資料的通訊端[conn1,conn2..] #r1就是select返回的有 # print(‘read_list:%s rl:%s wl:%s ‘ %(len(read_list),len(rl),len(wl))) #rl=[conn1,conn2]#注意: #1.剛開始迴圈r1裡面只有server,read_list=[server]裡面也只有server,此時r1和read_list裡面內筒一樣 #2.剛開始read_list=[server,conn] server是負責建立新串連的,conn是負責收訊息的 #3.當服務端accept()收到新的串連並加入到read_list[server,conn]裡面, # 問到結果之後此時 rl,wl,xl=select.select(read_list,write_list,[]),得到的r1裡面只包含已經有資料過來的串連 #read_list裡面的串連請求不會取走,只要有資料就不會阻塞,阻塞的情況是列表裡面沒有資料拿 #r1裡面去依次for迴圈取資料,如果是server通訊端對象就是accept(),否則就負責recv()資料 for sk in rl: #初始狀態read_list裡面放的的是server通訊端,需要執行accept操作 if sk == server: #判斷for迴圈,首先只有server服務端負責accept()接收 conn,addr=sk.accept() read_list.append(conn) #後面並發的數量多了時要往read_list裡面放一些有資料的通訊端對象 else: # sk.recv(1024) # print(sk) data=sk.recv(1024) write_list.append(sk) #有訊息往外回所以加進去了 data_dic[sk]=data #製作字典綁定send的對象和資料:格式為發送的對象conn:對應發送的資料 data #因為conn佔用了應用程式的資源、對應作業系統還有維持串連 for sk in wl: sk.send(data_dic[sk].upper()) #根據字典裡面對應的socket通訊端對象拿到,拿到 data_dic.pop(sk) #發完之後字典裡面就沒必要存放訊息了,所以就回收 write_list.remove(sk) #回完之後沒有了,所以就刪除 #write_list還沒滿的情況下會返回w1 #read_list占應用程式的資源 # 因為conn佔用了應用程式的資源、對應作業系統還要維持連結
#用戶端配置from socket import *import osclient=socket(AF_INET,SOCK_STREAM)client.connect((‘127.0.0.1‘,8080))while True: msg=input(‘輸入要操作的命令:‘) client.send(msg.encode(‘utf-8‘)) data=client.recv(1024) print(data.decode(‘utf-8‘))
Python IO多工select模組