#select 和 poll 和epoll的區別 ''' select和poll有一個共同的機制,都是採用輪訓的方式去詢問內核,有沒有數據準備好了 select有一個最大監聽事件的限制,32位機限制1024,,6位機限制2048 poll沒有,理論上poll能夠開啓無限大,1G內存大概夠你開10W個事件去監聽 epoll是最好的,採用的是回調機制,解決了select和poll共同存在的問題 並且epoll理論上也能夠開啓無限多個監聽事件 ''' # IO多路複用 ''' 阻塞IO 非阻塞IO 多路複用IO 異步IO python實現不了,可是有tornado框架,天生自帶異步 ''' #服務器端 import socket import select sk=socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() Conn_Del = [] #定義刪除列表 rlist = [sk] #是用來讓select幫忙監聽的全部接口 # select:windows/linux是監聽事件有沒有數據到來 # poll: linux 也能夠作select的工做 # epoll: linux 也能夠作相似的工做 while 1: r,w,x = select.select(rlist,[],[]) #將rlist傳給select,當rlist中哪一個接口有反應,就返回給r這個列表 if r: for i in r: #循環遍歷,看看有反應的接口是sk仍是conn,由於若是是sk,後面會把conn也加到這個列表中 if i == sk: #若是是sk,代表有客戶端的鏈接請求 conn,addr = i.accept() rlist.append(conn) #把新的客戶端的鏈接,添加到rlist,繼續讓select幫忙監聽 else: #若是是conn,表明客戶端請求發送數據了(此時客戶端已經鏈接上了) #下面的異常處理模型和非阻塞IO模型解決阻塞IO模型相似 try: msg = i.recv(1024).decode('utf-8') if not msg: #客戶端正常關閉返回給服務器端一個空,即客戶端執行了close() Conn_Del.append(i) i.close() else: #服務器端的邏輯層(以字符串大寫的形式返回給客戶端) print("接收到來自{}客戶端的消息{}".format(i,msg)) i.send(msg.upper().encode('utf-8')) except ConnectionResetError: #客戶端強制關閉 pass if Conn_Del: for conn in Conn_Del: rlist.remove(conn) Conn_Del.clear() sk.close() #客戶端 import socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) while 1: msg_s = input('>>>') if not msg_s:continue if msg_s == 'q':break sk.send(msg_s.encode('utf-8')) print(sk.recv(1024).decode('utf-8')) sk.close()