Python實例題:簡單的 Web 服務器

目錄

Python實例題

題目

要求:

解題思路:

代碼實現:

Python實例題

題目

簡單的 Web 服務器

要求

  • 使用 Python 的?socket?模塊實現一個簡單的 HTTP 服務器。
  • 支持以下功能:
    • 處理 GET 和 POST 請求
    • 靜態文件服務(HTML、CSS、JavaScript、圖片等)
    • 簡單的路由系統
    • 錯誤處理(404、500 等)
  • 添加多線程支持,以處理并發請求。

解題思路

  • 使用?socket?建立網絡連接。
  • 解析 HTTP 請求頭,處理不同類型的請求。
  • 使用線程池處理并發連接。

代碼實現

import socket
import threading
import os
import mimetypes
from urllib.parse import urlparse, parse_qsclass WebServer:def __init__(self, host='localhost', port=8080, document_root='www'):self.host = hostself.port = portself.document_root = document_rootself.routes = {'GET': {},'POST': {}}self.server_socket = Noneself.running = Falsedef route(self, method, path, handler):"""注冊路由處理函數"""self.routes[method][path] = handlerdef start(self):"""啟動服務器"""self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)self.server_socket.bind((self.host, self.port))self.server_socket.listen(5)self.running = Trueprint(f"服務器運行中: http://{self.host}:{self.port}")try:while self.running:client_socket, client_address = self.server_socket.accept()print(f"接受來自 {client_address} 的連接")# 創建線程處理請求client_handler = threading.Thread(target=self.handle_client,args=(client_socket,))client_handler.start()except KeyboardInterrupt:self.stop()def stop(self):"""停止服務器"""self.running = Falseif self.server_socket:self.server_socket.close()print("服務器已停止")def handle_client(self, client_socket):"""處理客戶端請求"""try:# 接收請求數據request_data = client_socket.recv(1024).decode('utf-8')if not request_data:return# 解析請求request_lines = request_data.splitlines()request_line = request_lines[0]method, path, _ = request_line.split(' ', 2)# 解析查詢參數parsed_url = urlparse(path)path = parsed_url.pathquery_params = parse_qs(parsed_url.query)# 處理 POST 請求體post_data = {}if method == 'POST':# 找到請求頭和請求體的分隔線body_index = request_data.find('\r\n\r\n')if body_index != -1:body = request_data[body_index + 4:]post_data = parse_qs(body)# 處理路由if path in self.routes[method]:response = self.routes[method][path](query_params, post_data)else:# 靜態文件服務response = self.serve_static_file(path)# 發送響應client_socket.sendall(response)except Exception as e:print(f"處理請求時出錯: {e}")error_response = self.generate_error_response(500)client_socket.sendall(error_response)finally:# 關閉連接client_socket.close()def serve_static_file(self, path):"""提供靜態文件服務"""# 處理根路徑if path == '/':path = '/index.html'# 構建文件路徑file_path = os.path.join(self.document_root, path[1:])# 檢查文件是否存在if not os.path.exists(file_path):return self.generate_error_response(404)# 檢查是否是目錄if os.path.isdir(file_path):return self.generate_error_response(403)try:# 讀取文件內容with open(file_path, 'rb') as file:content = file.read()# 確定 MIME 類型content_type, _ = mimetypes.guess_type(file_path)if not content_type:content_type = 'application/octet-stream'# 生成響應頭response_headers = (f'HTTP/1.1 200 OK\r\n'f'Content-Type: {content_type}\r\n'f'Content-Length: {len(content)}\r\n'f'\r\n').encode('utf-8')return response_headers + contentexcept Exception as e:print(f"讀取文件時出錯: {e}")return self.generate_error_response(500)def generate_error_response(self, status_code):"""生成錯誤響應"""status_messages = {404: 'Not Found',403: 'Forbidden',500: 'Internal Server Error'}status_message = status_messages.get(status_code, 'Error')# 生成錯誤頁面error_page = (f'<html><body><h1>{status_code} {status_message}</h1></body></html>').encode('utf-8')# 生成響應頭response_headers = (f'HTTP/1.1 {status_code} {status_message}\r\n'f'Content-Type: text/html\r\n'f'Content-Length: {len(error_page)}\r\n'f'\r\n').encode('utf-8')return response_headers + error_pagedef main():# 創建服務器實例server = WebServer(document_root='www')# 注冊動態路由def home_handler(query_params, post_data):response_body = '<html><body><h1>歡迎來到我的網站!</h1></body></html>'.encode('utf-8')response_headers = ('HTTP/1.1 200 OK\r\n''Content-Type: text/html\r\n'f'Content-Length: {len(response_body)}\r\n''\r\n').encode('utf-8')return response_headers + response_bodydef echo_handler(query_params, post_data):message = query_params.get('message', [''])[0]response_body = f'<html><body><p>你發送的消息是: {message}</p></body></html>'.encode('utf-8')response_headers = ('HTTP/1.1 200 OK\r\n''Content-Type: text/html\r\n'f'Content-Length: {len(response_body)}\r\n''\r\n').encode('utf-8')return response_headers + response_bodyserver.route('GET', '/', home_handler)server.route('GET', '/echo', echo_handler)# 啟動服務器try:server.start()except KeyboardInterrupt:passif __name__ == "__main__":main()

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/86832.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/86832.shtml
英文地址,請注明出處:http://en.pswp.cn/web/86832.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

3.Stable Diffusion WebUI本地部署和實踐

本文看了(68 封私信) 逼真的圖片生產 | Stable Diffusion WebUI本地部署看這一篇就夠了 - 知乎和(68 封私信) Stable Diffusion WebUI 實踐: 基本技法及微調 - 知乎&#xff0c;本人根據它們部署了一遍&#xff0c;中間遇到一些報錯&#xff0c;但根據報錯提示解決了問題&#…

阿里最新開源:Mnn3dAvatar 3D數字人框架, 無需聯網,本地部署可離線運行,支持多模態實時交互

Mnn3dAvatar 3D數字人框架是基于阿里巴巴開源的輕量級深度學習推理框架MNN&#xff08;Mobile Neural Network&#xff09;開發的全新3D數字人框架。Aibot親測這是一個可以在本地運行、完全離線、支持多模態實時交互的智能數字人App。可以在本地私有部署。感興趣的同學可以拿來…

03【C++ 入門基礎】函數重載

文章目錄 引言函數重載函數重載的使用函數重載的原理extern “C” 靜態多態 總結 引言 通過00【C 入門基礎】前言得知&#xff0c;C是為了解決C語言在面對大型項目的局限而誕生&#xff1a; C語言面對的現實工程問題&#xff08;復雜性、可維護性、可擴展性、安全性&#xff0…

改寫一個小項目: flask -------------------> next js

現在&#xff0c;請把上面改寫代碼的過程中&#xff0c;所有的過程&#xff0c;都寫下來&#xff0c;寫為文章的形式&#xff0c;內容比較長&#xff0c;你可以分多次輸出。而且要求語言幽默&#xff0c;苦中作樂的心態。分條理&#xff0c;要清晰。一場從 Flask 到 Next.js 的…

線性相關和線性無關

在線性代數中&#xff0c;線性相關和線性無關是刻畫向量組性質的核心概念&#xff0c;以下是關于它們的重要結論總結&#xff1a; 一、基本定義與核心判定 線性相關的定義 向量組 { α 1 , α 2 , … , α m } \{\alpha_1, \alpha_2, \dots, \alpha_m\} {α1?,α2?,…,αm?…

非常有科技感的wpf GroupBox 控件

效果 樣式 <Style TargetType="GroupBox"><Setter Property="Margin" Value="10,5" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="GroupBox"><Grid>&l…

【Java--SQL】${}與#{}區別和危害

目錄 一區別 二SQL${}注入問題 一區別 在MyBatis中&#xff0c;#{}和${}是兩種不同的參數占位符&#xff0c;用于在SQL語句中引用變量或參數。它們的區別如下&#xff1a; 1.#{}占位符&#xff08;預編譯&#xff09;&#xff1a;#{}是MyBatis中的預編譯占位符&#xff0c;…

【科技核心期刊推薦】計算機與數字工程

【論文發表利器】《計算機技術與工程應用》——工程技術領域的學術新天地&#xff01; 作為計算機技術與工程應用交叉領域的前沿期刊&#xff0c;《計算機技術與工程應用》期刊&#xff0c;聚焦算法、系統結構、信息融合與安全、圖像處理等方向&#xff0c;為學術界提供了一個…

導出docker-compse.yml中docker鏡像成tar文件

#!/bin/bash # 確保腳本在正確的目錄下運行 SCRIPT_DIR$(dirname "$(realpath "$0")") cd "$SCRIPT_DIR" || exit 1 # 定義docker-compose文件路徑 COMPOSE_FILE"${SCRIPT_DIR}/docker-compose.yml" # 創建導出目錄 EXPORT_DIR"$…

ECMAScript 2019(ES2019):數組與對象操作的精細化升級

1.版本背景與發布 發布時間&#xff1a;2019年6月&#xff0c;由ECMA International正式發布&#xff0c;標準編號為ECMA-262 10th Edition。歷史意義&#xff1a;作為ES6之后的第四次年度更新&#xff0c;ES2019聚焦于數組、對象和字符串操作的精細化改進&#xff0c;提升開發…

2.1.1 配置堡壘機以控制Linux資產文件傳輸

文章目錄 一、試題及考試說明二、操作步驟1. 啟動JumpServer服務&#xff0c;瀏覽器登錄&#xff08;admin/Sjtu1896&#xff09;2. 創建堡壘機用戶&#xff0c;用戶名為“ops01”格式命名&#xff0c;郵箱以為“ops01jumpserver.cn”&#xff0c;使用密碼“admin123”&#xf…

react ant-design通用頁面自適應適配不同分辨率屏幕的方法工具類

該方法會根據 目標分辨率&#xff08;options.width/height&#xff09; 和 當前窗口尺寸&#xff08;innerWidth/innerHeight&#xff09; 計算縮放比例&#xff0c;并保持 等比例縮放&#xff08;Math.min(scaleX, scaleY)&#xff09;&#xff0c;確保內容不變形&#xff1a…

基于IEC61499實現的工業機器視覺方案

1.什么是機器視覺 機器視覺就是賦予機器看懂圖像的能力。它是一門涉及人工智能、計算機科學、圖像處理、光學、機械工程和自動化的交叉技術領域。核心目標是&#xff1a;通過攝像頭或其他成像設備獲取圖像或視頻&#xff0c;然后利用計算機算法對這些圖像進行分析和理解&#x…

機電一體化論文寫作實戰指南:從創新設計到工程驗證的完整路徑

機電論文的“技術-表達”鴻溝 某高校團隊研發的智能抓取系統實物表現優異&#xff0c;卻被審稿人質疑&#xff1a; “未說明機電耦合設計對性能的影響”——這揭示了機電一體化研究的核心痛點&#xff1a;強工程弱理論。本文基于217篇高影響力論文&#xff0c;拆解從技術到寫作…

MySQL 配置參數調優:根據工作負載調整服務器設置

MySQL 數據庫的默認配置參數是為了適應各種通用場景而設定的,它們通常無法最大化發揮服務器硬件的潛力,也無法完全匹配特定應用程序的工作負載。一個未優化的 MySQL 配置,在面對高并發、大數據量或特定查詢模式時,很容易成為系統性能的瓶頸。 配置參數調優,就是根據你的服…

嵌入式Linux驅動開發基礎-2 LED驅動

imx6ull中GPIO涉及寄存器 1&#xff1a;CCM寄存器 GPIOx 要用 CCM_CCGRy 寄存器中的 2 位來決定該組 GPIO 是否使能。哪組 GPIO 用哪個 CCM_CCGR 寄存器來設置。 CCM_CCGR 寄存器中某 2 位的取值含義如下&#xff1a; 00 &#xff1a;該 GPIO 模塊全程被關閉 01 &…

深度解析】使用Go語言實現JWT:從原理到實踐

JWT&#xff08;JSON Web Token&#xff09;已成為現代Web應用中身份驗證的基石。本文深入剖析如何用Go語言實現JWT&#xff0c;從基礎概念、底層機制到完整代碼實踐&#xff0c;助你全面掌握。 一、JWT概述 JWT是一種開放標準&#xff08;RFC 7519&#xff09;&#xff0c;用…

深入解讀 DeepSeek-V3 架構及落地的挑戰

從多專家架構&#xff08;MoE&#xff09;到模型落地實戰的一線觀察 一、引言&#xff1a;DeepSeek-V3 是什么&#xff1f; 在大模型百花齊放的今天&#xff0c;DeepSeek-V3 作為 DeepSeek 系列的第三代開源模型&#xff0c;不僅延續了高質量對話能力&#xff0c;還在架構上邁…

前端進階之路-從傳統前端到VUE-JS(第二期-VUE-JS框架結構分析)

經過上期內容的學習&#xff0c;我們已經可以構建一個VUE-CLI框架了&#xff0c;接下來我們分析一下這個框架&#xff0c;畢竟知己知彼&#xff0c;百戰百勝 我們創建完成后可以看到以下內容 接下來我們分析一下他的文件結構 node_modules用于存放項目所依賴的第三方模塊和包…

網絡協議 / 加密 / 簽名總結

加密方式&#xff1a; 對稱加密&#xff1a;key 不可公開。 非對稱加密&#xff1a;公鑰加密的信息只有私鑰能解密。私鑰加密的信息只有公鑰能解密&#xff0c;且公鑰只能解密私鑰加密的信息&#xff08;用于簽名&#xff09;。 非對稱加密應用&#xff1a; 簽名&#xff1a…