网络与应用层
从服务处理的角度来看,网络的核心目的在于通过协议控制,实现请求端与服务端之间数据的完整交互。
对请求端和服务端而言,中间层的报文封装、转发、路由等行为是不可感知的。网络层和传输层共同构建了一个抽象的“一致交互环境”,使得远端传输的数据能够被“原封不动地”接收并存储到本地缓存,供应用逻辑处理。
正因为中间网络的不可见性与“穿透性”,网络层与传输层的协议设计更强调通用性与可靠性。它们的关注点在于数据的可靠传递与顺序控制,而不是数据的具体内容,因此协议结构通常具有严格的头部格式与字段定义,以保证设备间的互通与协议的一致性。
相较之下,应用层协议更关注的是“如何处理数据”。它所需考虑的,是服务需要哪些输入字段、输出以何种格式表达。因而,应用层协议具备更强的灵活性与语义扩展性,核心是围绕字段的定义、解析与业务映射,完成服务端与请求端的语义协同。
网络层和传输层协议通常强调字段的控制意义和状态管理功能,例如通过设置特定位(如 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()
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 :
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()
|
可以看到 其工作流程:
- 创建TCP 服务器,绑定网卡地址和端口地址
2.开始监听外部请求
3.定义循环来处理接收到的消息
4.接收到的http请求被处理成字符串 请求头一般包含 方法,路径,协议版本 和一些头控制信息
- 可以通过请求头解析出对应的路径,这里设计了一个装饰器,将被装饰的函数添加到整体的路由字典中,当请求头中的字段存在于字典中时执行对应的函数,否则执行默认函数。默认函数会将默认的响应头和HTML字段,对http请求做出响应。
整体上HTTP的工作流程是 :
服务器监听→ 服务端发起请求→ 服务端分析文本信息,路由到请求的目标资源,执行对应的函数,将数据返回给请求端,关闭socket。