04-返回指定页面内容
目标¶
- 能够实现 根据浏览器不同请求
返回对应网页资源
的Web服务器
1. 功能分析¶
1、Web服务器能够绑定固定端口
2、Web服务器端能够接收浏览器请求
3、Web服务器遵守HTTP协议,根据请求返回指定的html 内容给浏览器
4、当浏览器关闭后,Web服务器能够显示断开连接
5、Web服务器短时间内重启,不会提示 address already in use 错误
2. 实现思路¶
1、导入socket模块
2、创建tcp套接字
3、设置地址重用
4、绑定端口
5、设置监听,最大允许客户端连接数128(套接字有主动变为被动)
6、等待客户端连接(能够接受多个客户端连接)
7、定义函数,实现客户端信息接收和响应
8、接收浏览器请求,并判断请求是否为空
9、拼接响应报文
10、定义变量保存响应报文内容
11、获取浏览器发送的请求头信息,分析并得到请求html文件路径
12、根据路径信息,打开指定的html文件,并返回内容给客户端浏览器
13、发送响应报文给客户端浏览器(注意转码问题)
14、关闭此次连接的套接字
3. 代码实现¶
import socket
import re
def request_handler(new_client_socket):
""" 响应客户端请求的核心函数 """
request_data = new_client_socket.recv(1024)
# 判断客户端是否已经断开链接
if not request_data:
print("客户端已经断开连接!")
# 关闭当前连接
new_client_socket.close()
# 退出,代码不再向后执行
return
# 目的:得到 客户端 请求行
# 对客户端请求的数据进行分析
request_data_str = request_data.decode()
# 根据”\r\n“ 分割请求头,得到存储每行请求数据的列表
request_list = request_data_str.split("\r\n")
# print(request_list)
# 使用正则 取出 请求头中的 路径部分
ret = re.search(r"\s(.*)\s", request_list[0])
if not ret:
print("用户请求报文格式错误!")
new_client_socket.close()
return
# 得到路径
path_info = ret.group(1)
print("接收到用户请求:", path_info)
response_header = "Server:Python-Web1.0\r\n"
response_blank = "\r\n"
try:
# 读取指定路径文件,并且返回
with open("static"+path_info, "rb") as file:
# 读取文件的二进制数据
response_content = file.read()
except Exception as e:
# 开始拼接响应数据
response_line = "HTTP/1.1 404 Not Found\r\n"
response_content = "Error !!! %s" % str(e)
response_content = response_content.encode()
else:
# 开始拼接响应数据
response_line = "HTTP/1.1 200 OK\r\n"
# 拼接响应头
response_data = (response_line + response_header + response_blank).encode() + response_content
# 发送数据
new_client_socket.send(response_data)
# 关闭socket
new_client_socket.close()
def main():
# 创建套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置地址重用
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定IP 和端口
tcp_server_socket.bind(("", 8080))
# 设置套接字为被动套接字,主要接收客户端链接
tcp_server_socket.listen(128)
while True:
# 接受客户端链接
new_client_socket, ip_port = tcp_server_socket.accept()
print("[新客户端上线]", ip_port)
# 相应客户端请求,发送数据给客户端
request_handler(new_client_socket)
if __name__ == '__main__':
main()
4. 默认首页判断¶
# 设置默认请求页面为 index.html
if path_info == "/":
path_info = "/index.html"
运行结果: