#方法:sk.setblocking(False) #服務器端: import socket sk=socket.socket() sk.setblocking(False) sk.bind(('127.0.0.1',8080)) sk.listen() #定義空列表用於存放各個conn Conn_List = [] #定義刪除列表用於刪除Conn_List中斷開鏈接的客戶端conn Conn_Del = [] while 1: try: conn,addr = sk.accept() #若是是阻塞IO,此時程序會一直在這裏等待 Conn_List.append(conn) #將監聽到的conn對象放到conn列表中,即爲多客戶端鏈接 except BlockingIOError: '''若是try中沒有客戶端鏈接,則執行該代碼塊,判斷客戶端是否向服務器發送數據''' #遍歷conn列表,看看有沒有客戶端發送數據 for conn in Conn_List: try: #嘗試接收數據 info = conn.recv(1024).decode('utf-8') #注意!若是客戶端正常關閉,即客戶端執行了close,服務器會接收到一個空 if not info: #若是收到空,證實客戶端斷開鏈接,將該conn添加到刪除列表中,用於後面刪除Conn_List中對應的conn Conn_Del.append(conn) print('客戶端已經斷開鏈接了') #在服務器中關閉對應的conn conn.close() else: '''服務器邏輯層''' # 若是收到客戶端的數據,邏輯層返回數據給客戶端 print('這是接收到來自客戶端{}的數據:{}'.format(conn,info)) #返回數據給客戶端(例如將客戶端的數據小寫轉爲大寫返回給客戶端) conn.send(info.upper().encode('utf-8')) except BlockingIOError: '''若是本次循環中該conn沒有發送數據,則執行該代碼塊,即對下一個conn通訊''' continue except ConnectionResetError: '''若是本次循環中該conn強制退出,則不執行任何操做''' pass #刪除列表刪除Conn_List中已經正常斷開鏈接的客戶端conn if Conn_Del: for conn in Conn_Del: Conn_List.remove(conn) #在刪除完正常關閉連接的客戶端後,應該把刪除列表清空,不然會報錯 Conn_Del = [] #客戶端: 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()