Python 编写简易 HTTP 服务器
什么是 HTTP
HTTP(HyperText Transfer Protocol,超文本传输协议)是一个应用层协议。准确来说,它是基于 TCP/IP 四层网络模型中传输层的 TCP 协议之上的应用层协议。
在网络通信中,用户的数据是以报文来传输的。在实际通信中,每一层都会对包进行封装,从而形成段、数据报、帧,最后是以比特流(二进制)进行传输。到了目标主机后,会对每一层又进行拆解,从而得到最后的报文。
HTTP 位于最上层,即应用层。它最初被用来传输 Hypertext 文档,因此被称为超文本协议。虽然现在可以传输视频、音频、图片等其他类型的数据,但它依然沿用此名称。
HTTP 报文结构分析
HTTP 报文由四部分组成:起始行、首部行、空白行以及实体(Body)。各部分之间使用 \r\n(CRLF)进行分割。
请求报文格式
在 Linux 中,可以使用 curl -v 网址 命令打印详细的请求信息,其中包括报文内容。
curl -v http://example.com
请求报文格式如下:
- 请求行:指定 HTTP 请求方法(如 GET、POST、HEAD)、URL 路径及协议版本,以 CRLF 结束。
- 首部行:可以有多个,以 (字段名:值) 的方式出现,每个首部行同样以 CRLF 结束。常见的有 User-Agent、Host、Accept 等。
- 空白行:代表 HTTP 报文头结束,接下来是报文主体。
- 实体:请求的主体内容,GET 请求通常为空,POST 请求则包含表单数据或 JSON 等。
响应报文格式
响应报文结构与请求报文类似,主要区别在于第一行:
- 状态行:包含协议版本、状态码(如 200, 301, 404)以及状态短语(如 OK, Moved Permanently)。
- 首部行:告知服务器信息、时间、报文类型(Content-Type)及长度(Content-Length)。
- 空白行:分隔头部与主体。
- 实体:服务器返回的具体内容,如 HTML 代码、JSON 数据或文件流。
使用 Python 手写 HTTP 服务器
HTTP 是基于 TCP 的应用层协议,构建 HTTP 服务器的本质是编写一个 Socket 程序。
基础 Socket 实现
以下是一个简单的 Python TCP 服务器示例,监听本地回环地址的 8080 端口,并处理客户端请求。
import socket
# 创建 TCP 套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口复用,避免重启时报错
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定地址和端口
server_address = ('127.0.0.1', 8080)
server_socket.bind(server_address)
# 开始监听
server_socket.listen(5)
print('Server listening on port 8080...')
try:
while True:
# 接受客户端连接
client_socket, client_address = server_socket.accept()
print(f'Connection from {client_address}')
try:
# 接收客户端请求数据
data = client_socket.recv(1024).decode('utf-8')
if not data:
continue
# 解析请求行(简单示例)
request_line = data.split('\r\n')[0]
print(f'Request: {request_line}')
# 构建 HTTP 响应
response_body = 'Hello, Destined Person.'
response_headers = f'Content-Length: {len(response_body)}\r\nContent-Type: text/plain; charset=utf-8'
response = f'HTTP/1.1 200 OK\r\n{response_headers}\r\n\r\n{response_body}'
# 发送响应
client_socket.sendall(response.encode('utf-8'))
finally:
# 关闭客户端连接
client_socket.close()
except KeyboardInterrupt:
print('Shutting down server...')
finally:
server_socket.close()
运行测试
启动上述脚本后,可以在终端使用 curl 进行测试:
curl -v http://127.0.0.1:8080
如果配置正确,将看到服务器返回的 HTTP 200 状态码及自定义消息。
生产环境建议
虽然手动编写 Socket 服务器有助于理解原理,但在实际开发中,我们通常使用成熟的 Web 框架或标准库。
- 标准库:Python 内置了
http.server模块,可以快速搭建一个简单的 HTTP 服务器用于静态文件服务。python -m http.server 8000 - Web 框架:对于复杂业务,推荐使用 Flask、Django 或 FastAPI 等框架。它们遵循 WSGI(Web Server Gateway Interface)标准,提供了路由、中间件、ORM 等丰富功能。
- WSGI 说明:文章开头提到的 WSGI 是 Python Web 应用的接口标准,它定义了 Web 服务器如何与 Python 应用程序通信,是构建高性能 Python Web 服务的基础。
总结
本文介绍了 HTTP 协议的基本概念、请求与响应报文的结构,并通过 Python Socket 编程演示了如何构建一个简单的 HTTP 服务器。通过对比原始 Socket 实现与标准库及框架的差异,可以看出底层原理与上层抽象之间的关系。掌握这些基础知识,有助于深入理解网络编程及 Web 开发的运行机制。

