• web服务器


    服务器实现:

    import socket
    import re
    import gevent
    from gevent import monkey
    import sys
    
    monkey.patch_all()  # 自动切换  time.sleep recv accept 这些类型的函数在执行的时候会出现大量的耗时等待,所以让这部分闲置时间加以利用.
    
    
    class HTTPServer:
        """web服务"""
        def __init__(self, port):
            """初始化操作"""
            # 1. 创建tcp服务器的socket  设置选项 绑定 监听
            server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            server_socket.bind(('', port))  # 这里绑定的是服务器的固定端口,目的是让客户端能连接到了我的机器上面之后,可以找到我的这个程序
            server_socket.listen(128)
    
            # 将socket对象保存在 当前对象的属性中
            self.server_socket = server_socket
    
        def start(self):
            """启动服务"""
            while True:
                client_socket, client_addr = self.server_socket.accept()
                print('接受到%s的连接请求' % str(client_addr))
                # 为每个用户创建一个协程,并且启动 运行
                gevent.spawn(self.client_handler, client_socket)
    
        def client_handler(self, client_socket):
            """处理每个客户端的请求"""
            # 3.接收用户请求报文
            request_data = client_socket.recv(4096)
            # 解码 bytes  --> str
            request_data_str = request_data.decode()
            print(request_data)
            # ps:当用户的请求路径为/时候,表示其请求的是首页 homepage
            # 解析用户请求 获取到用户的资源请求路径
            # 正则匹配 只要是有/ 提取请求路径
            # GET /index.html
            result = re.search(r'^w+ (/S*)', request_data_str)
            # 判断是否提取成功  成功就取出这个值,不成功结束程序
            if not result:  # 路径为空
                print('请求报文格式错误')
                client_socket.close()
                # 结束 这种情况
                return
    
            # 尽量扁平结构 不要使用else缩进去,那样的是嵌套结构,这是小技巧
            # 获取请求路径  资源路径<static> + /index.html
            # 如果执行到这里,一定是匹配成功了,因为失败的已经跳过了
            path_info = result.group(1)
    
            # 4.返回用户指定的文件数据作为响应体   打包到响应报文中  static + /index.html
            # static 是文件夹,open打不开 潜规则 :所有的web服务器 不写路径默认是主页
    
            # 如果path_info 是/,返回 index首页
            if path_info == '/':
                path_info = '/index.html'
    # ---------------------------动态资源请求-------------------------->
            # 如果是动态资源,需要调用框架来处理  python中.html结尾的就是动态资源
            env = {
                'PATH_INFO': path_info  # 实际情况下web服务器会将所有的请求信息放到字典中,env是字典类型参数
            }
            if path_info.endswith('.html'):
                import Application
    
                status, headers, response_body = Application.app(env)
                # 先拼接响应行
                response_line = 'HTTP/1.1 %s
    ' % status
                response_header = ''
                for name, value in headers:
                    response_header += '%s:%s
    ' % (name, value)
                response_data = response_line + response_header + '
    ' + response_body
                client_socket.send(response_data.encode())
                client_socket.close()
    # -------------------------静态资源的处理----------------------->
            else:
                # 静态资源的处理
                try:
                    with open('static' + path_info, 'rb') as file:
                        html_data = file.read()  # html_data 是二进制bytes字节类型的数据
                except Exception as e:
                    with open('static/404.html', 'rb') as file:
                        html_data = file.read()
                    response_data = ('HTTP/1.1 404 Not Found
    Server: PWS3.0Plus
    
    ').encode() + html_data
                else:
                    # .encode()先把前面的str类型转成bytes字节类型,然后拼接
                    response_data = ('HTTP/1.1 200 OK
    Server: PWS3.0Plus
    
    ').encode() + html_data
    
                finally:
                    # 统一最后发送
                    client_socket.send(response_data)
                    # 5.一次请求/响应 就关闭连接  --> 短连接
                    client_socket.close()
    
    
    def main():
        # 获取程序运行所需的参数<端口>   python3  1.py  8080  argv:['x.py',8080]
        if len(sys.argv) < 2:
            print('参数使用出错,应该是形如:python3 07-web服务器-命令行参数控制内部绑定的端口.py 8080')
        # 端口号是一个数字
        port = int(sys.argv[1])
    
        # 创建web服务
        http_server = HTTPServer(port)
        # 启动web服务
        http_server.start()
    
    
    if __name__ == '__main__':
        main()
  • 相关阅读:
    HDU 5363 Key Set(快速幂取模)
    HDU 5339 Untitled(暴搜)
    POJ 2406 Power Strings
    Dedecms备份还原网站有效方法
    DEDECMS文章列表每隔8行文章添加分隔虚线
    DEDECMS突破TAG和关键字长度的限制
    为织梦dedecms制作全文RSS订阅源
    DedeCms中Channel用typeid无效
    织梦CMS/Dedecms添加自定义函数
    sql批量换dedecms文章来源和作者
  • 原文地址:https://www.cnblogs.com/huaibin/p/12101017.html
Copyright © 2020-2023  润新知