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端存在性能問題,所以它不能無限的去開啓線程,也就是說服務的開啓的進程數或線程數都會隨着併發的客戶端數目地增多而增多,這會對服務端主機帶來巨大的壓力,甚至於不堪重負而癱瘓,因而咱們必須對服務端開啓的線程數加以控制,讓機器在一個本身能夠承受的範圍內運行。 併發
而解決的辦法就是利用「線程池」:線程池就是用來存放線程的池子,本質仍是基於多線程,只不過是對開啓線程的數目加上了限制:socket
基於線程池的多線程的Server端的代碼以下:ide
# -*- 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個客戶端與服務器端通訊,因此當第三個客戶端試圖去與服務器端創建連接時是沒有用的,只有當其中的一個客戶端停掉才能通訊:post