HTTP 就是浏览器和服务器之间的"对话协议"。 浏览器说: "GET /hello HTTP/1.1\r\nHost: localhost\r\n\r\n" 服务器答: "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello" 就这么简单。HTTP 只是在 TCP 连接上传递的文本格式。
()
| 100 | # ============================================================ |
| 101 | |
| 102 | def lesson_2_http_server(): |
| 103 | """ |
| 104 | HTTP 就是浏览器和服务器之间的"对话协议"。 |
| 105 | |
| 106 | 浏览器说: "GET /hello HTTP/1.1\r\nHost: localhost\r\n\r\n" |
| 107 | 服务器答: "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello" |
| 108 | |
| 109 | 就这么简单。HTTP 只是在 TCP 连接上传递的文本格式。 |
| 110 | """ |
| 111 | print("\n" + "=" * 60) |
| 112 | print("第二课: 亲手写一个 HTTP 服务器") |
| 113 | print("=" * 60) |
| 114 | |
| 115 | # 方法 1: 用最原始的 socket 写一个 HTTP 服务器 |
| 116 | print("\n --- 方法 1: 用 raw socket 实现 ---") |
| 117 | print(" 这是最底层的方式,帮你理解 HTTP 到底是什么") |
| 118 | |
| 119 | def raw_http_server(): |
| 120 | """一个只用 socket 的 HTTP 服务器""" |
| 121 | server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| 122 | server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
| 123 | server.bind(("127.0.0.1", 0)) # 端口 0 = 让系统自动分配 |
| 124 | port = server.getsockname()[1] |
| 125 | server.listen(1) |
| 126 | server.settimeout(3) |
| 127 | return server, port |
| 128 | |
| 129 | server_sock, port = raw_http_server() |
| 130 | print(f" 服务器启动在 127.0.0.1:{port}") |
| 131 | |
| 132 | # 在后台线程处理一个请求 |
| 133 | response_body = '{"message": "hello from raw socket server!"}' |
| 134 | |
| 135 | def handle_one_request(): |
| 136 | try: |
| 137 | client, addr = server_sock.accept() |
| 138 | # 读取请求(简化: 只读一次) |
| 139 | request_data = client.recv(1024).decode() |
| 140 | first_line = request_data.split("\r\n")[0] |
| 141 | |
| 142 | # 构造 HTTP 响应——就是一段文本 |
| 143 | response = ( |
| 144 | "HTTP/1.1 200 OK\r\n" |
| 145 | f"Content-Length: {len(response_body)}\r\n" |
| 146 | "Content-Type: application/json\r\n" |
| 147 | "\r\n" |
| 148 | f"{response_body}" |
| 149 | ) |
| 150 | client.sendall(response.encode()) |
| 151 | client.close() |
| 152 | return first_line |
| 153 | except socket.timeout: |
| 154 | return None |
| 155 | |
| 156 | thread = threading.Thread(target=handle_one_request) |
| 157 | thread.start() |
| 158 | |
| 159 | # 作为客户端请求这个服务器 |
no test coverage detected