標籤:Python 簡單web伺服器實現
import socketimport reimport geventfrom gevent import monkey monkey.patch_all()# 識別等待時間,讓協程切換def client_handler(client_socket): ‘‘‘接收用戶端連結請求,響應對應的的資料‘‘‘ # 接收資料 request_data = client_socket.recv(4096) # 判斷是否接收到資料 if not request_data: print("用戶端已經取消連結") client_socket.close() return # 對接收到的用戶端請求資料進行解碼 request_str_data = request_data.decode() #對請求的報文進行分割,分割出一個請求各行數列表 data_list = request_str_data.split("\r\n") # 拿到請求行資料,請求行資料是列表第0個元素 request_line = data_list[0] # 通過正則匹配到我們請求的檔案路徑 result = re.match(r"\w+\s+(\S+)", request_line) # 判斷匹配的請求檔案路徑是否存在 if not result: print("請求路徑不存在") client_socket.close() return path_info = result.group(1) print("使用者請求資訊%s" % str(path_info)) # 佈建要求網域名稱預設跳轉首頁 if path_info == "/": # 指定首頁地址 path_info = "/index.html" # 回應標頭 response_header = "Server: PWS1.0\r\n" try: # 響應體,開啟用戶端請求的資料 with open("./html" + path_info, "rb") as file: file_data = file.read() except Exception as e: # 構造請求錯誤響應報文 response_line = "HTTP/1.1 404 NOT FOUND\r\n" response_body = "EROOR!!! %s".center(800) %(e) # 拼接響應報文 response_data = response_line + response_header + "\r\n" + response_body # 給用戶端發送響應報文 client_socket.send(response_data.encode()) else: # 構造請求成功響應報文 response_line = "HTTP/1.1 200 OK\r\n" response_body = file_data response_data = (response_line + response_header + "\r\n").encode() + response_body # 發送響應報文 client_socket.send(response_data) finally: # 關閉通訊端 client_socket.close()# 建立主函數,定義通訊端def main(): # 建立通訊端,指定IP和資料報類型 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 設定連接埠複用 server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # 設定綁定,監聽,接收連結 server_socket.bind(("", 4433)) server_socket.listen(128) # 伺服器是面向多客戶,迴圈接收用戶端請求連結 while True: client_socket, client_address = server_socket.accept() print("服務端接收到來自%s的連結請求" % str(client_address)) # 處理連結請求 # client_handler(client_socket) # 建立協程實現多任務 g1 = gevent.spawn(client_handler, client_socket) # 保持主進程存活(阻塞主進程,等待協程g1執行完再退出) # g1.join()# 程式入口if __name__ == ‘__main__‘: main()物件導向封裝上面代碼
import socketimport reimport geventfrom gevent import monkeyimport sysmonkey.patch_all()# 識別等待時間,讓協程切換class HTTPServer(object): def __init__(self, port): """完成執行個體對象的初始化操作""" # 建立通訊端,指定IP和資料報類型 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 設定連接埠複用 server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # 設定綁定,監聽,接收連結 server_socket.bind(("", 4433)) server_socket.listen(128) # 通訊端對象的引用 self.server_socket = server_socket # 通訊端的連結等待 def start(self): # 伺服器是面向多客戶,迴圈接收用戶端請求連結 while True: client_socket, client_address = self.server_socket.accept() print("服務端接收到來自%s的連結請求" % str(client_address)) # 處理連結請求 # client_handler(client_socket) # 建立協程實現多任務 g1 = gevent.spawn(self.client_handler, client_socket) # 保持主進程存活(阻塞主進程,等待協程g1執行完再退出) #g1.join() def client_handler(self, client_socket): ‘‘‘接收用戶端連結請求,響應對應的的資料‘‘‘ # 接收資料 request_data = client_socket.recv(4096) # 判斷是否接收到資料 if not request_data: print("用戶端已經取消連結") client_socket.close() return # 對接收到的用戶端請求資料進行解碼 request_str_data = request_data.decode() #對請求的報文進行分割,分割出一個請求各行數列表 data_list = request_str_data.split("\r\n") # 拿到請求行資料,請求行資料是列表第0個元素 request_line = data_list[0] # 通過正則匹配到我們請求的檔案路徑 result = re.match(r"\w+\s+(\S+)", request_line) # 判斷匹配的請求檔案路徑是否存在 if not result: print("請求路徑不存在") client_socket.close() return path_info = result.group(1) print("使用者請求資訊%s" % str(path_info)) # 佈建要求網域名稱預設跳轉首頁 if path_info == "/": # 指定首頁地址 path_info = "/index.html" # 回應標頭 response_header = "Server: PWS1.0\r\n" try: # 響應體,開啟用戶端請求的資料 with open("./html" + path_info, "rb") as file: file_data = file.read() except Exception as e: # 構造請求錯誤響應報文 response_line = "HTTP/1.1 404 NOT FOUND\r\n" response_body = "EROOR!!! %s".center(800) %(e) # 拼接響應報文 response_data = response_line + response_header + "\r\n" + response_body # 給用戶端發送響應報文 client_socket.send(response_data.encode()) else: # 構造請求成功響應報文 response_line = "HTTP/1.1 200 OK\r\n" response_body = file_data response_data = (response_line + response_header + "\r\n").encode() + response_body # 發送響應報文 client_socket.send(response_data) finally: # 關閉通訊端 client_socket.close()# 建立主函數,定義通訊端,設定命令列自訂連接埠運行def main(): # 判斷輸入命令參數是否符合要求 if len(sys.argv) != 2: print("正確開啟檔案: python3 運行程式.py 連接埠號碼") return if not sys.argv[1].isdigit(): print("正確開啟檔案: python3 運行程式.py 連接埠號碼") return port = int(sys.argv[1]) http_server = HTTPServer(port) http_server.start()# 程式入口if __name__ == ‘__main__‘: main()
Python簡單實現Web伺服器