静态web服务器
一、返回固定页面的静态web服务器
返回固定页面的静态web服务器很容易实现,步骤如下:
- 编写一个TCP服务端程序
- 接收到浏览器的http请求
- 读取固定页面的数据,把数据组装成HTTP响应报文发送给浏览器
- 关闭服务于客户端的socket
代码如下:
import socket # 创建socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置端口复用,程序退出端口立即释放 server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # 绑定端口 server_socket.bind(('', 12345)) # 开启监听 server_socket.listen(5) while True: # 等待客户端连接 server_client_socket, client_addr = server_socket.accept() # 接收客户端连接的数据 recv_data = server_client_socket.recv(4096) # 对接收的数据进行解码打印 print(recv_data.decode('utf-8')) # 响应行 response_line = 'HTTP/1.1 200 OK\r\n' # 响应头 response_header = 'Server: MYWEBSERVER1.0\r\n' # html页面 with open('static/index.html', 'rb') as f: resp_data = f.read() # 响应体 response_body = resp_data # 拼接响应报文数据 response_data = (response_line + response_header + '\r\n').encode('utf-8') + response_body # 发送给客户端 server_client_socket.send(response_data) # 关闭与客户端连接的套接字 server_client_socket.close()
运行上述代码,在浏览器输入 http://127.0.0.1:12345/ 即可访问固定的页面。
二、返回指定页面的静态web服务器
返回指定页面的静态web服务器也非常简单,只需要在接收到浏览器请求时,获取请求的资源路径,根据资源路径读取指定文件的数据,再将读取的数据组装成响应报文发送给浏览器即可;如果请求的资源不存在,则组装404状态的响应报文发给浏览器。
代码如下:
import socket def my_server(): server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置端口号复用, 程序退出端口立即释放 server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # 绑定端口 server_socket.bind(('', 12345)) # 开启监听 server_socket.listen(5) while True: # 等待接收客户端连接请求 server_client_socket, ipaddr = server_socket.accept() # 接收客户端发送的数据(即浏览器发送的请求报文) recv_data_content = server_client_socket.recv(4096) # 判断是否为空 if len(recv_data_content) == 0: print('关闭连接') server_client_socket.close() return # 请求报文 开始是类似 GET / HTTP/1.1 的请求行 recv_data = recv_data_content.decode('utf-8') # 请求行(GET / HTTP/1.1)在最开始,使用空格进行分割得到列表,列表第二个元素即是资源路径 request_path = recv_data.split(' ', maxsplit=2)[1] # 如果是请求/ ,指定返回首页 if request_path == '/': request_path = '/index.html' try: with open('static/' + request_path, 'rb') as f: # 响应体 resp_data = f.read() # 响应行 response_line = 'HTTP/1.1 200 OK\r\n' # 响应头 response_header = 'Server: MyWebSERVER 1.0\r\n' # 拼接响应报文 response_data = (response_line + response_header + '\r\n').encode('utf-8') + resp_data # 发送响应报文 server_client_socket.send(response_data) # 如果请求的资源不存在 except Exception as e: # 响应行 response_line = 'HTTP/1.1 404 Not Found\r\n' # 响应头 response_header = 'Server: MyWebSERVER 1.0\r\n' # 响应体 with open('static/error.html', 'rb') as f: resp_data = f.read() # 拼接响应报文 response_data = (response_line + response_header + '\r\n').encode('utf-8') + resp_data # 发送数据 server_client_socket.send(response_data) finally: server_client_socket.close() if __name__ == '__main__': my_server()
上述代码不支持多个客户端同时访问,如果要同时处理多个请求,可使用多进程或多线程。推荐使用多线程。
对上述代码修改如下:
import socket, threading def my_server(server_client_socket): # 接收客户端发送的数据(即浏览器发送的请求报文) recv_data_content = server_client_socket.recv(4096) # 请求报文 开始是类似 GET / HTTP/1.1 的请求行 recv_data = recv_data_content.decode('utf-8') # 请求行(GET / HTTP/1.1)在最开始,使用空格进行分割得到列表,列表第二个元素即是资源路径 request_path = recv_data.split(' ', maxsplit=2)[1] print(request_path) # 如果是请求/ 指定返回首页 if request_path == '/': request_path = '/index.html' try: with open('static/' + request_path, 'rb') as f: # 响应体 resp_data = f.read() # 响应行 response_line = 'HTTP/1.1 200 OK\r\n' # 响应头 response_header = 'Server: MyWebSERVER 1.0\r\n' # 拼接响应报文 response_data = (response_line + response_header + '\r\n').encode('utf-8') + resp_data # 发送响应报文 server_client_socket.send(response_data) # 如果请求的资源不存在 except Exception as e: # 响应行 response_line = 'HTTP/1.1 404 Not Found\r\n' # 响应头 response_header = 'Server: MyWebSERVER 1.0\r\n' # 响应体 with open('static/error.html', 'rb') as f: resp_data = f.read() # 拼接响应报文 response_data = (response_line + response_header + '\r\n').encode('utf-8') + resp_data # 发送数据 server_client_socket.send(response_data) finally: server_client_socket.close() if __name__ == '__main__': server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置端口号复用, 程序退出端口立即释放 server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # 绑定端口 server_socket.bind(('', 12345)) # 开启监听 server_socket.listen(5) while True: # 等待客户端连接 server_client_socket, client_addr = server_socket.accept() # 客户端连接上服务端时建立子线程 sub_thread = threading.Thread(target=my_server, args=(server_client_socket,)) # 设置守护线程 sub_thread.daemon = True # 开始执行子线程的任务,即my_server函数 sub_thread.start()
运行上述程序,浏览器输入http://127.0.0.1:12345/ 即可访问首页,输入http://127.0.0.1:12345/资源路径 ,如果资源存在,则访问指定的资源,不存在则接收到404状态响应,访问到指定的错误页面。
浙公网安备 33010602011771号