Python编程 VIII HTTP服务

网络与应用层

从服务处理的角度来看,网络的核心目的在于通过协议控制,实现请求端与服务端之间数据的完整交互

对请求端和服务端而言,中间层的报文封装、转发、路由等行为是不可感知的。网络层和传输层共同构建了一个抽象的“一致交互环境”,使得远端传输的数据能够被“原封不动地”接收并存储到本地缓存,供应用逻辑处理。

正因为中间网络的不可见性与“穿透性”,网络层与传输层的协议设计更强调通用性与可靠性。它们的关注点在于数据的可靠传递与顺序控制,而不是数据的具体内容,因此协议结构通常具有严格的头部格式与字段定义,以保证设备间的互通与协议的一致性。

相较之下,应用层协议更关注的是“如何处理数据”。它所需考虑的,是服务需要哪些输入字段、输出以何种格式表达。因而,应用层协议具备更强的灵活性与语义扩展性,核心是围绕字段的定义、解析与业务映射,完成服务端与请求端的语义协同。

网络层和传输层协议通常强调字段的控制意义和状态管理功能,例如通过设置特定位(如 TCP 的 SYN、ACK、FIN)来标识连接状态或数据传输的阶段,以及通过 IP 层的 TTL、标志位等控制报文的转发行为。

相比之下,应用层协议更强调字段的语义描述性,即字段用于表达请求的操作类型、参数内容或格式要求,具体的状态(如会话是否有效、登录是否成功)通常由客户端和服务端通过各自的逻辑来维护。应用层字段本身通常不维护传输状态,而是作为触发状态变化或状态校验的依据。

HTTP

HTTP协议是什么?

HTTP 是一种基于请求-响应模式的应用层协议,客户端通过构建结构化的请求报文(包括请求方法、资源路径、请求头和可选的请求体)来描述其访问意图,服务端根据这些信息进行解析、路由、处理,并生成结构化的响应返回。

请求

HTTP请求包含三部分

1.请求行:说明请求类型(GET、POST 等)、资源路径和协议版本。

请求行描述了 请求的资源对象,以及请求的方法。

2.请求头:携带客户端环境、请求意图、身份验证、缓存规则等元数据。

请求头描述了一些交互的控制信息,

3.请求体(可选):例如 POST 请求中发送的数据。

1
2
3
4
5
6
7
请求示例

GET /index.html HTTP/1.1
Host: [www.example.com](http://www.example.com/)
User-Agent: MyBrowser/2.0
Connection: keep-alive
Accept: text/html
1
2
3
4
5
6
7
8
9
10
11
12
13
响应示例 

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 75
Cache-Control: max-age=3600
Connection: keep-alive

<html>
<body>
<h1>Hello, HTTP/1.1!</h1>
</body>
</html>

Python的HTTP实现示例

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
import socket

HOST = '127.0.0.1' # 监听所有地址
PORT = 4623 # 监听端口
PATH_ROUTE = {}
def path_add(path_name):
def wapper(func) :
PATH_ROUTE[path_name] = func
return wapper

@path_add("/home")
def get_home_method(conn):
response_body = "<html><body><h1>Hello, World! Here is home page</h1></body></html>"
response = (
"HTTP/1.1 200 OK\r\n"
f"Content-Length: {len(response_body.encode())}\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n"
"\r\n"
f"{response_body}"
)

conn.sendall(response.encode())
conn.close()

@path_add("/index")
def get_index_method(conn):
response_body = "<html><body><h1>Hello, World! Here is index page</h1></body></html>"
response = (
"HTTP/1.1 200 OK\r\n"
f"Content-Length: {len(response_body.encode())}\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n"
"\r\n"
f"{response_body}"
)

conn.sendall(response.encode())
conn.close()

# 创建 socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST, PORT))
server_socket.listen(5)

print(f"HTTP Server running at http://{HOST}:{PORT}")

while True:
client_conn, client_addr = server_socket.accept()
request = client_conn.recv(1024).decode()

print(f"\n----- Received request from {client_addr} -----")
print(request.strip())

content = request.splitlines()
method,path,protocol = content[0].split(" ")
rout_name = path.split(".")[0]
if rout_name in PATH_ROUTE :
PATH_ROUTE[rout_name]()
continue
else :

# 构造 HTTP 响应内容
response_body = "<html><body><h1>Hello, World!</h1></body></html>"
response = (
"HTTP/1.1 200 OK\r\n"
f"Content-Length: {len(response_body.encode())}\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n"
"\r\n"
f"{response_body}"
)

client_conn.sendall(response.encode())
client_conn.close()

可以看到 其工作流程:

  1. 创建TCP 服务器,绑定网卡地址和端口地址

2.开始监听外部请求

3.定义循环来处理接收到的消息

4.接收到的http请求被处理成字符串 请求头一般包含 方法,路径,协议版本 和一些头控制信息

  1. 可以通过请求头解析出对应的路径,这里设计了一个装饰器,将被装饰的函数添加到整体的路由字典中,当请求头中的字段存在于字典中时执行对应的函数,否则执行默认函数。默认函数会将默认的响应头和HTML字段,对http请求做出响应。

整体上HTTP的工作流程是 :

服务器监听→ 服务端发起请求→ 服务端分析文本信息,路由到请求的目标资源,执行对应的函数,将数据返回给请求端,关闭socket。


Python编程 VIII HTTP服务
http://gadoid.io/2025/04/17/Python编程-VIII-HTTP服务/
作者
Codfish
发布于
2025年4月17日
许可协议