01-静态web服务器(Python)-面向对象的对比

普通写法,静态web服务器:

  • 先创建TCP服务器套接字,然后等待客户端(这里是浏览器)请求连接。
  • 客户端发起请求,用线程来处理连接的建立,这样可以实现多任务(也就是并发)
  • 连接后根据请求发送指定页面

补充:设置守护主线程:当主线程退出,子线程立马全死

  1 import socket
  2 import os
  3 import threading
  4 
  5 # 处理客户端的请求
  6 def handle_client_request(new_socket):
  7     # 代码执行到此,说明连接建立成功
  8     # 连接客户端的请求信息
  9     recv_data = new_socket.recv(4096)
 10     # 判断接收到的数据长度是否为0
 11     if len(recv_data) == 0:  # 用来解决客户端一连接服务器就关闭的现象
 12         new_socket.close()
 13         return
 14 
 15     # 对二进制数据进行解码
 16     recv_content = recv_data.decode("UTF-8")
 17     print(recv_data)
 18 
 19     # 对数据按照空格进行分割(maxsplit=2表示分割两次,得到3个。其格式为元组)
 20     request_list = recv_content.split(" ", maxsplit=2)
 21     # 获取请求的资源路径
 22     request_path = request_list[1]
 23     print(request_path)
 24 
 25     # 判断请求的是否是根目录,如果是根目录设置返回的信息
 26     if request_path == "/":
 27         request_path = "/index.html"
 28 
 29     # 判断该路径的文件是否存在,有两种方法
 30     # 方法一:os.path.exists
 31     # os.path.exists("static/" + request_path)
 32     # 方法二:try-except异常抛出的4件套
 33 
 34     try:
 35         # 打开文件读取文件中的数据,提示:这里使用rb模式,兼容打开图片文件(用二进制的方式)
 36         with open("static" + request_path, "rb") as file:  # 这里的file表示打开文件的对象
 37             file_data = file.read()
 38         # 提示:with open  关闭文件这步操作不用程序来完成,系统帮我们完成
 39 
 40     except Exception as e:
 41         # 代码执行到此,说明没有请求的该文件,返回404状态信息
 42         # 响应行
 43         response_line = "HTTP/1.1 404 Not Found
"
 44         # 响应头
 45         response_header = "Server:PWS/1.0
"
 46         # 空行
 47 
 48         # 读取404页面数据
 49         with open("static/error.html", "rb") as file:
 50             file_data = file.read()
 51         # 响应体
 52         response_body = file_data
 53 
 54         # 把数据封装成http,响应报文格式的数据
 55         response = (response_line +
 56                     response_header +
 57                     "
").encode("UTF-8") + response_body
 58 
 59         # 发送给浏览器的响应报文数据
 60         new_socket.send(response)
 61 
 62     else:
 63         # 代码执行到此,说明文件存在,返回200状态信息
 64         # 响应行
 65         response_line = "HTTP/1.1 200 OK
"
 66         # 响应头
 67         response_header = "Server: pws/1.0
"
 68         # 空行
 69         # 响应体
 70         response_body = file_data
 71 
 72         # 把数据封装成http,响应报文格式的数据
 73         response = (response_line +
 74                     response_header +
 75                     "
").encode("UTF-8") + response_body  # 响应行/头是字符串,响应体是二进制。
 76         # 这里把响应行/头也改成二进制,再连接起来
 77         # 发送给浏览器的响应报文数据
 78         new_socket.send(response)
 79 
 80     finally:
 81         # 关闭服务于客户端的套接字
 82         new_socket.close()
 83 
 84 
 85 def main():
 86     # 创建TCP服务器套接字
 87     tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 88     # 设置端口号复用,程序退出端口号立即释放
 89     tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
 90     # 绑定端口号
 91     tcp_server_socket.bind(("", 8000))
 92     # 设置监听
 93     tcp_server_socket.listen(128)
 94     # 循环等待接受客户端的连接请求
 95     while True:
 96         # 等待接受客户端的连接请求
 97         new_socket, ip_port = tcp_server_socket.accept()
 98         # 当客户端和服务器建立连接,创建子线程
 99         sub_thread = threading.Thread(target=handle_client_request, args=(new_socket,))
100         # 设置守护主线程
101         sub_thread.setDaemon(True)
102         # 启动子线程执行的对应任务
103         sub_thread.start()
104 
105 
106 if __name__ == '__main__':
107     main()

面向对象的写法:

  • 用类进行封装,
  • TCP服务器套接字直接写在__init__里面,这样默认就会创建
  1 import socket
  2 import os
  3 import threading
  4 
  5 
  6 # Http协议的web服务器类
  7 class HttpWebServer(object):
  8     def __init__(self):
  9         # 创建TCP服务器套接字
 10         tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 11         # 设置端口号复用,程序退出端口号立即释放
 12         tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
 13         # 绑定端口号
 14         tcp_server_socket.bind(("", 8000))
 15         # 设置监听
 16         tcp_server_socket.listen(128)
 17         # 把TCP服务器的套接字做为web服务器对象的属性
 18         self.tcp_server_socket = tcp_server_socket
 19 
 20     # 处理客户端请求
 21     @staticmethod
 22     def handle_client_request(new_socket):
 23         # 代码执行到此,说明连接建立成功
 24         # 连接客户端的请求信息
 25         recv_data = new_socket.recv(4096)
 26         # 判断接收到的数据长度是否为0
 27         if len(recv_data) == 0:  # 用来解决客户端一连接服务器就关闭的现象
 28             new_socket.close()
 29             return
 30 
 31         # 对二进制数据进行解码
 32         recv_content = recv_data.decode("UTF-8")
 33         print(recv_data)
 34 
 35         # 对数据按照空格进行分割(maxsplit=2表示分割两次,得到3个。其格式为元组)
 36         request_list = recv_content.split(" ", maxsplit=2)
 37         # 获取请求的资源路径
 38         request_path = request_list[1]
 39         print(request_path)
 40 
 41         # 判断请求的是否是根目录,如果是根目录设置返回的信息
 42         if request_path == "/":
 43             request_path = "/index.html"
 44 
 45         # 判断该路径的文件是否存在,有两种方法
 46         # 方法一:os.path.exists
 47         # os.path.exists("static/" + request_path)
 48         # 方法二:try-except异常抛出的4件套
 49 
 50         try:
 51             # 打开文件读取文件中的数据,提示:这里使用rb模式,兼容打开图片文件(用二进制的方式)
 52             with open("static" + request_path, "rb") as file:  # 这里的file表示打开文件的对象
 53                 file_data = file.read()
 54             # 提示:with open  关闭文件这步操作不用程序来完成,系统帮我们完成
 55 
 56         except Exception as e:
 57             # 代码执行到此,说明没有请求的该文件,返回404状态信息
 58             # 响应行
 59             response_line = "HTTP/1.1 404 Not Found
"
 60             # 响应头
 61             response_header = "Server:PWS/1.0
"
 62             # 空行
 63 
 64             # 读取404页面数据
 65             with open("static/error.html", "rb") as file:
 66                 file_data = file.read()
 67             # 响应体
 68             response_body = file_data
 69 
 70             # 把数据封装成http,响应报文格式的数据
 71             response = (response_line +
 72                         response_header +
 73                         "
").encode("UTF-8") + response_body
 74 
 75             # 发送给浏览器的响应报文数据
 76             new_socket.send(response)
 77 
 78         else:
 79             # 代码执行到此,说明文件存在,返回200状态信息
 80             # 响应行
 81             response_line = "HTTP/1.1 200 OK
"
 82             # 响应头
 83             response_header = "Server: pws/1.0
"
 84             # 空行
 85             # 响应体
 86             response_body = file_data
 87 
 88             # 把数据封装成http,响应报文格式的数据
 89             response = (response_line +
 90                         response_header +
 91                         "
").encode("UTF-8") + response_body  # 响应行/头是字符串,响应体是二进制。
 92             # 这里把响应行/头也改成二进制,再连接起来
 93             # 发送给浏览器的响应报文数据
 94             new_socket.send(response)
 95 
 96         finally:
 97             # 关闭服务于客户端的套接字
 98             new_socket.close()
 99 
100     # 启动服务器的方法
101     def start(self):
102         # 循环等待接受客户端的连接请求
103         while True:
104             # 等待接受客户端的连接请求
105             new_socket, ip_port = self.tcp_server_socket.accept()
106             # 当客户端和服务器建立连接,创建子线程
107             sub_thread = threading.Thread(target=self.handle_client_request, args=(new_socket,))
108             # 设置守护主线程
109             sub_thread.setDaemon(True)
110             # 启动子线程执行的对应任务
111             sub_thread.start()
112 
113 def main():
114     # 创建web服务器
115     web_server = HttpWebServer()
116     # 启动服务器
117     web_server.start()
118 
119 if __name__ == '__main__':
120     main()
Linux学习笔记
原文地址:https://www.cnblogs.com/zealwang/p/13476550.html