基于HTTP模拟实现静态服务器-协程实现

来源:互联网 发布:徽标在线制作软件 编辑:程序博客网 时间:2024/05/16 17:36

“””
根据用户访问的时候 指定的路径 服务器返回指定的页面数据
使用面向对象方式实现
“””
from gevent import monkey
monkey.patch_all()
import gevent
import re
import socket

“””
a 创建一个TCP监听的套接字 接受到客户端的连接请求
b 接收客户端的请求报文
c 根据HTTP的请求报文格式进行解析
d 根据HTTP的响应报文格式进行响应
“”“

```class HTTPServer(object):    def __init__(self):        """初始化对象 相关属性"""        # 创建一个TCP监听的套接字 接受到客户端的连接请求        self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        # 地址重用 在重启的时候能够立马重用相关的地址和端口 1表示设置 0表示取消设置        self.tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)        # 绑定端口        self.tcp_socket.bind(('', 8888))        # 将套接字设置为被动监听模式        self.tcp_socket.listen(128)    def start(self):        # 循环接收客户端请求 ---        while True:            client_socket, client_addr = self.tcp_socket.accept()            print("收到来自%s的连接请求" % str(client_addr))            #  对客户端的请求  进行处理            # 创建并且执行一个协程 单独为每个客户进行服务            # 破解patch_all -------> recv recvfrom accept 如果没有数据 就能够自动被gevent切换            gevent.spawn(self.client_handler, client_socket)    def client_handler(self, client_socket):        """处理客户端请求  并且予以相应"""        # 接收客户端的HTTP请求报文 --- 数据        data = client_socket.recv(4096)        if not data:            print("客户端断开了连接")            client_socket.close()            return        # 对请求数据进行解码操作        str_data = data.decode()        # 拆分出请求报文中的每一行 解析用户的请求路径        data_list = str_data.split("\r\n")        # print(data_list)        # 获取请求行数据 第0行 GET /path/a/ab/index.html HTTP/1.1        request_line = data_list[0]        result = re.match(r"\w+\s+(\S+)", request_line)        if not result:            # 表明请求的格式不合法            client_socket.close()            return        # 格式合法  根据正则提取出用户请求的路径信息        path_info = result.group(1)        print("收到用户请求路径" + path_info)        # 当用户访问/的时候  访问的是/index.html        if path_info == '/':            # index.html一般代表一个网站的首页            path_info = '/index.html'        # HTTP响应报文格式        """        成功 HTTP/1.1 200 OK\r\nServer: pythonserver\r\n\r\n页面数据        失败 HTTP/1.1 404 Not Found\r\nServer: pythonserver\r\n\r\n页面数据        用户页面上看到的数据 其实就是服务器本地的文件数据        """        # 响应相关的数据 ---- 根据响应报文格式 拼接相关数据        # 响应行数据        # 服务器指定的数据目录 + 用户请求的目录        #        # static           + /index.html  /home/it/001.txt        try:            # 以二进制方式打开文件 读的文件数据就是Bytes类型            file = open("static" + path_info, "rb")            # 如果文件数据很大 则会出现隐患            file_data = file.read()            file.close()        except Exception as e:            # 如果用户请求的路径不存在 则打开文件失败            response_data = "HTTP/1.1 404 Not Found\r\n"            # 头部数据            response_data += "Server: PythonServer4.0\r\n"            # 空行            response_data += "\r\n"            # 响应体数据            response_data += "EROOR"            # response_data str---> bytes            client_socket.send(response_data.encode())        else:            # 打开文件成功            # 文件数据就是响应体数据            response_data = "HTTP/1.1 200 OK\r\n"            # 头部数据            response_data += "Server: PythonServer4.0\r\n"            # 空行            response_data += "\r\n"            # 如果响应的文件数据是 图片 音频 视频等二进制资源 不能进行decode操作            response_body = file_data            response_data = response_data.encode() + response_body            # send函数的返回值的含义 表示成功发送的字节数            data_len = client_socket.send(response_data)            # print("数据长度%d 发送的大小是%d" % (len(response_data), data_len))            # 如果想要将数据全部发送完成 可以使用sendall()            # client_socket.sendall(response_data)        finally:            # 在发生异常 或者没有发生异常的情况下 都会执行这一步            client_socket.close()def main():    # 创建一个HTTPServer实例对象    http_server = HTTPServer()    # 开始启动http_server  接受客户端连接请求  创建相关的服务处理客户端请求    http_server.start()if __name__ == '__main__':    main()    # 客户端请求方式  在浏览器中输入 http://127.0.0.1:8080/
原创粉丝点击