python 併發伺服器 面向連線 多程序 多執行緒 單程序
面向連線的併發伺服器
def main(): # 1. 建立socket套接字 tcp_server = socket(AF_INET, SOCK_STREAM) # 2. 繫結IP地址和埠 tcp_server.bind(("", 8888)) # 3. 把主動模式變成被動模式 只能接收 不能傳送資料 tcp_server.listen(5) while True: # 4. 等待客戶端連線 new_socket, client_info = tcp_server.accept() print(f"新的客戶端來了 {client_info}") # 5. 接收資料 raw_data = new_socket.recv(1024) while raw_data: print(f"收到{client_info}資料: {raw_data}") # 再次取 raw_data = new_socket.recv(1024) # 6.關閉新套接字 new_socket.close() if __name__ == '__main__': main()
只能同時為一個人服務
多程序併發伺服器
from socket import * from multiprocessing import Process def rec_data(client_info, new_socket): """新套接字處理資料""" raw_data = new_socket.recv(1024) while raw_data: print(f"收到{client_info}資料: {raw_data}") # 再次取 raw_data = new_socket.recv(1024) # 關閉套接字 new_socket.close() def main(): # 1. 建立socket套接字 tcp_server = socket(AF_INET, SOCK_STREAM) # 2. 繫結IP地址和埠 tcp_server.bind(("", 7777)) # 3. 把主動模式變成被動模式 只能接收 不能傳送資料 tcp_server.listen(5) while True: # 4. 等待客戶端連線 new_socket, client_info = tcp_server.accept() print(f"新的客戶端來了 {client_info}") # 5. 接收資料 # rec_data(client_info, new_socket) # 6.建立新的程序 p = Process(target=rec_data, args=(client_info, new_socket)) # 6.1 啟動程序 p.start() # 6.關閉新套接字 多程序必需關閉new_socket因為會複製出來一個新的 new_socket.close() if __name__ == '__main__': main()
多程序伺服器代表:Apache伺服器
主程序中必需關閉new_socket.close()
多執行緒併發伺服器
from socket import * from threading import Thread def rec_data(client_info, new_socket): """新套接字處理資料""" raw_data = new_socket.recv(1024) while raw_data: print(f"收到{client_info}資料: {raw_data}") # 再次取 raw_data = new_socket.recv(1024) # 關閉套接字 new_socket.close() def main(): # 1. 建立socket套接字 tcp_server = socket(AF_INET, SOCK_STREAM) # 2. 繫結IP地址和埠 tcp_server.bind(("", 7788)) # 3. 把主動模式變成被動模式 只能接收 不能傳送資料 tcp_server.listen(5) while True: # 4. 等待客戶端連線 new_socket, client_info = tcp_server.accept() print(f"新的客戶端來了 {client_info}") # 5. 接收資料 # rec_data(client_info, new_socket) # 6.建立新的程序 p = Thread(target=rec_data, args=(client_info, new_socket)) # 6.1 啟動程序 p.start() # 6.關閉新套接字 #new_socket.close() if __name__ == '__main__': main()
多執行緒代表:IIS伺服器
子執行緒共享主執行緒的變數,所以主執行緒中不能關閉new_socket.close(),否則子執行緒也會斷開連線
單程序非阻塞版併發伺服器
from socket import * def main(): # 1. 建立socket套接字 tcp_server = socket(AF_INET, SOCK_STREAM) # 2. 把套接字設定成非阻塞 tcp_server.setblocking(False) # 2. 繫結IP地址和埠 tcp_server.bind(("", 6667)) # 3. 把主動模式變成被動模式 只能接收 不能傳送資料 tcp_server.listen(5) # 4. 宣告一個列表用來存新的套接字 socket_lists = [] while True: try: # 4. 等待客戶端連線 new_socket, client_info = tcp_server.accept() # 4.1 設定new_socket為非阻塞 new_socket.setblocking(False) except: pass else: """已經有人連線,取到資料了""" # 把新的套接字往列表裡扔 socket_lists.append((new_socket, client_info)) print(f"新的客戶端來了 {client_info}") # 迴圈列表 for sock, client_info in socket_lists: try: # 讓每一個new_socket去接收資料 又阻塞了,應該在建立new_socket後設置新的套接字為 非阻塞 raw_data = sock.recv(1024) except: pass else: # 當客戶端斷開的時候 raw_data 就是空 if raw_data: print(f"收到{client_info}資料:{raw_data.decode('gb2312')}") else: # 客戶端斷了 sock.close() # 列表移除 socket_lists.remove((sock, client_info)) if __name__ == '__main__': main()