【05】Python搭建简单服务器
Python动态服务器网页(需要使用WSGI接口),基本实现步骤如下:
1.等待客户端的链接,服务器会收到一个http协议的请求数据报
2.利用正则表达式对这个请求数据报进行解析(请求方式、提取出文件的环境)
3.提取出文件的环境之后,利用截断取片的方法将文件名转化为模块名称
4.使用m = __import__(),就可以得到返回值为m的模块
5.创建一个env字典:其中包含的是请求方式及文件环境等各种的键值对
6.创建一个新的动态脚本,其中定义了application这个函数,必须包含env和start_response的参数(也是服务器里的调用方法)
7.在这个动态脚本中定义状态码status和响应头headers(注意是字典形式,如Content-Type)
8.然后再调用start_response(status,headers),但是要注意,这个函数在服务器被定义
9.在动态脚本中编写动态执行程序
10.m.appliction的返回值就是回应数据包的body,它的数据头在start_response被整合
11.将数据头与数据body拼接起来,然后发送给客户端,就可显示动态网页
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | MyWebServer # coding:utf-8 import socket import re import sys from multiprocessing import Process from MyWebFramework import Application # 设置静态文件根目录 HTML_ROOT_DIR = "./html" WSGI_PYTHON_DIR = "./wsgipython" class HTTPServer( object ): """""" def __init__( self , application): """构造函数, application指的是框架的app""" self .server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self .server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 ) self .app = application def start( self ): self .server_socket.listen( 128 ) while True : client_socket, client_address = self .server_socket.accept() #print("[%s,%s]用户连接上了" % (client_address[0],client_address[1])) print ( "[%s, %s]用户连接上了" % client_address) handle_client_process = Process(target = self .handle_client, args = (client_socket,)) handle_client_process.start() client_socket.close() def start_response( self , status, headers): """ status = "200 OK" headers = [ ("Content-Type", "text/plain") ] star """ response_headers = "HTTP/1.1 " + status + "\r\n" for header in headers: response_headers + = "%s: %s\r\n" % header self .response_headers = response_headers def handle_client( self , client_socket): """处理客户端请求""" # 获取客户端请求数据 request_data = client_socket.recv( 1024 ) print ( "request data:" , request_data) request_lines = request_data.splitlines() for line in request_lines: print (line) # 解析请求报文 # 'GET / HTTP/1.1' request_start_line = request_lines[ 0 ] # 提取用户请求的文件名 print ( "*" * 10 ) print (request_start_line.decode( "utf-8" )) file_name = re.match(r "\w+ +(/[^ ]*) " , request_start_line.decode( "utf-8" )).group( 1 ) method = re.match(r "(\w+) +/[^ ]* " , request_start_line.decode( "utf-8" )).group( 1 ) env = { "PATH_INFO" : file_name, "METHOD" : method } response_body = self .app(env, self .start_response) response = self .response_headers + "\r\n" + response_body # 向客户端返回响应数据 client_socket.send(bytes(response, "utf-8" )) # 关闭客户端连接 client_socket.close() def bind( self , port): self .server_socket.bind(("", port)) def main(): sys.path.insert( 1 , WSGI_PYTHON_DIR) if len (sys.argv) < 2 : sys.exit( "python MyWebServer.py Module:app" ) # python MyWebServer.py MyWebFrameWork:app module_name, app_name = sys.argv[ 1 ].split( ":" ) # module_name = "MyWebFrameWork" # app_name = "app" m = __import__ (module_name) app = getattr (m, app_name) http_server = HTTPServer(app) # http_server.set_port http_server.bind( 8000 ) http_server.start() if __name__ = = "__main__" : main() |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | MyWebFrameWork # coding:utf-8 import time # from MyWebServer import HTTPServer # 设置静态文件根目录 HTML_ROOT_DIR = "./html" class Application( object ): """框架的核心部分,也就是框架的主题程序,框架是通用的""" def __init__( self , urls): # 设置路由信息 self .urls = urls def __call__( self , env, start_response): path = env.get( "PATH_INFO" , "/" ) # /static/index.html if path.startswith( "/static" ): # 要访问静态文件 file_name = path[ 7 :] # 打开文件,读取内容 try : file = open (HTML_ROOT_DIR + file_name, "rb" ) except IOError: # 代表未找到路由信息,404错误 status = "404 Not Found" headers = [] start_response(status, headers) return "not found" else : file_data = file .read() file .close() status = "200 OK" headers = [] start_response(status, headers) return file_data.decode( "utf-8" ) for url, handler in self .urls: #("/ctime", show_ctime) if path = = url: return handler(env, start_response) # 代表未找到路由信息,404错误 status = "404 Not Found" headers = [] start_response(status, headers) return "not found" def show_ctime(env, start_response): status = "200 OK" headers = [ ( "Content-Type" , "text/plain" ) ] start_response(status, headers) return time.ctime() def say_hello(env, start_response): status = "200 OK" headers = [ ( "Content-Type" , "text/plain" ) ] start_response(status, headers) return "hello itcast" def say_haha(env, start_response): status = "200 OK" headers = [ ( "Content-Type" , "text/plain" ) ] start_response(status, headers) return "hello haha" urls = [ ( "/" , show_ctime), ( "/ctime" , show_ctime), ( "/sayhello" , say_hello), ( "/sayhaha" , say_haha), ] app = Application(urls) # if __name__ == "__main__": # urls = [ # ("/", show_ctime), # ("/ctime", show_ctime), # ("/sayhello", say_hello), # ("/sayhaha", say_haha), # ] # app = Application(urls) # http_server = HTTPServer(app) # http_server.bind(8000) # http_server.start() |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 电商平台中订单未支付过期如何实现自动关单?
· 用 .NET NativeAOT 构建完全 distroless 的静态链接应用
· 为什么构造函数需要尽可能的简单
· 探秘 MySQL 索引底层原理,解锁数据库优化的关键密码(下)
· 大模型 Token 究竟是啥:图解大模型Token
· 如何开发 MCP 服务?保姆级教程!
· 1.net core 工作流WorkFlow流程(介绍)
· 瞧瞧别人家的限流,那叫一个优雅!
· 从零散笔记到结构化知识库:我的文档网站建设之路
· 一文彻底搞懂 MCP:AI 大模型的标准化工具箱