Socket“服務器-客戶端”模型的多線程並發實現效果的大體思路是:首先,在Server端建立“鏈接循環”,每一個鏈接都開啟一個“線程”,使得每一個Client端都能通過已經建立好的線程來同時與Server通信,代碼如下:

# -*- coding: utf-8 -*- # -*- Author: WangHW -*- import socket from threading import Thread def Communication(conn): # 通信循環 while 1: try: data = conn.recv(1024) if not data: break print('Client Data:', data.decode('utf-8')) conn.send(data.upper()) except ConnectionResetError: break def Server(ip,post): whw_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) whw_server.bind((ip,post)) whw_server.listen(5) # 鏈接循環 while 1: conn, addr = whw_server.accept() #創建線程 t = Thread(target=Communication,args=(conn,)) t.start() if __name__ == '__main__': #主線程干Server的工作 Server('127.0.0.1',9000)

# -*- coding: utf-8 -*- # -*- Author: WangHW -*- import socket whw_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) whw_client.connect(('127.0.0.1',9000)) while 1: msg = input('>>>:').strip() if not msg: continue whw_client.send(msg.encode('utf-8')) data = whw_client.recv(1024) print('Server Data:',data.decode('utf-8'))
運行效果如下:
但是,這樣的設計存在一個十分嚴重的問題:由於Server端存在性能問題,因此它不能無限的去開啟線程,也就是說服務的開啟的進程數或線程數都會隨着並發的客戶端數目地增多而增多,這會對服務端主機帶來巨大的壓力,甚至於不堪重負而癱瘓,於是我們必須對服務端開啟的線程數加以控制,讓機器在一個自己可以承受的范圍內運行。
而解決的辦法就是利用“線程池”:線程池就是用來存放線程的池子,本質還是基於多線程,只不過是對開啟線程的數目加上了限制:
基於線程池的多線程的Server端的代碼如下:

# -*- coding: utf-8 -*- # -*- Author: WangHW -*- import socket from concurrent.futures import ThreadPoolExecutor def Communication(conn): # 通信循環 while 1: try: data = conn.recv(1024) if not data: break print('Client Data:', data.decode('utf-8')) conn.send(data.upper()) except ConnectionResetError: break def Server(ip,post): whw_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) whw_server.bind((ip,post)) whw_server.listen(5) # 鏈接循環 while 1: conn, addr = whw_server.accept() pool.submit(Communication,conn) if __name__ == '__main__': #最多可開client端為2個 pool = ThreadPoolExecutor(2) #主線程干Server的工作 Server('127.0.0.1',9000)
我們在線程池設置了最多可以有2個客戶端與服務器端通信,所以當第三個客戶端試圖去與服務器端建立鏈接時是沒有用的,只有當其中的一個客戶端停掉才能通信: