python3 简单实现 web 静态服务器

from gevent import monkey
monkey.patch_all()
import re
import gevent
from socket import *


class HttpServer(object):
    """HTTP服务器类"""
    def __init__(self):
        # 创建一个TCP的监听套接字 ,接受客户端的连接请求
        self.server_sock = socket(AF_INET, SOCK_STREAM)
        # 地址重设 , 在重启的时候能立即释放端口, 1 表示设置 0 表示取消设置
        self.server_sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        # 绑定端口
        self.server_sock.bind(('', 7724))
        # 将主动套接字转变为被动套接字
        self.server_sock.listen(128)

    def start(self):
        # 循环接受客户端请求
        while True:
            client_sock, client_adr = self.server_sock.accept()
            print("收到来自%s的请求" % str(client_adr))
            # 创建并启动协程
            # 破解patch_all ----> recv,recvfrom,accept 如果没有数据 就能够自动被gevent自动切换
            gevent.spawn(self.handle_client, client_sock)

    def handle_client(self, client_socket):
        # 接受客户端的HTTP报文 ---数据
        rec_data = client_socket.recv(4096).decode()
        # 判断如果接受的数据为空, 即客户端断开连接
        if not rec_data:
            client_socket.close()
            print("客户端断开了连接")
            return
        # 拆分出请求报文的每一行 返回一个列表
        data_list = rec_data.splitlines()
        # 解析用户的请求路径 ,获取请求行数据 第0行
        request_line = re.match(r"\w+\s+(\S+)", data_list[0])
        # 如果输入的地址有误 ,断开连接
        if not request_line:
            # 表明请求的格式不合法
            client_socket.close()
            print("输入的地址有误")
            return
        # 格式合法 根据正则提取出用户请求的路径信息
        path_info = request_line.group(1)
        # 当用户访问"/"时 ,自动跳转到 "/index.html"
        if path_info == "/":
            # index.html 一般代表一个网站的首页
            path_info = "/index.html"

        try:
            # 以二进制方式打开文件,文件的目录=服务器指定的目录+用户请求的目录, 读取的文件类型是bytes类型
            with open("static" + path_info, "rb") as file:
                file_content = file.read()
        except Exception as e:
            # 如果用户请求的路径不存在 则会抛出404 不存在 错误
            response_data = "HTTP/1.1 404 NOT FOUND\r\n"
            # 头部数据
            response_data += "server: Python Server Hyper1.0\r\n"
            # 空行
            response_data += "\r\n"
            # 响应体数据 根据响应报文的格式 拼接相关数据
            response_data += "404NOTFOUND" * 1000
            # 将响应体数据编码发送
            client_socket.send(response_data.encode())
        else:
            # 打开文件成功  文件数据就是响应体数据
            response_data = "HTTP/1.1 200 OK\r\n"
            response_data += "server: Python Server Hyper1.0\r\n"
            response_data += "\r\n"
            # 如果响应的文件数据是图片,音频, 视频的等二进制资源 ,则不能进行decode操作
            response_body = response_data.encode() + file_content
            # send函数返回值的含义是表示成功发送的字节数,如果想要全部发送, 可以使用sendall
            client_socket.send(response_body)
        finally:
            # 不管有无发生异常,都会执行套接字关闭
            client_socket.close()



def main():
    # 创建一个HttpServer的实例对象
    http_server = HttpServer()
    # 开始启动http_server
    http_server.start()

if __name__ == '__main__':
    main()

你可能感兴趣的:(python)