欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python-web:web服务器+动态资源‘框架’1

程序员文章站 2022-07-15 11:16:06
...

前:

Python-web:web服务器+动态资源‘框架’1

服务器的种类有很多比如Nginx、Apache等等,这涉及到了服务器的性能,故有了服务器自己的技术,那么如何让自己的动态资源框架实现忽略这些不同的web服务器呢,于是就有了WSGI协议。

Python-web:web服务器+动态资源‘框架’1

web服务器+动态资源‘框架’ 模拟

1.文件结构图:

Python-web:web服务器+动态资源‘框架’1

Python-web:web服务器+动态资源‘框架’1

2.参考代码

web_server.py

# 让web服务器支持WSGI协议

# 面对对象的方式
# 多进程实现
# 补充知识点:F5是刷新(不过很多时候都是用的浏览器缓存);用ctrl+r 强制刷新。
import socket, re
import multiprocessing
import time
# import dynamic.mini_frame
from dynamic import mini_frame

class WSGIServer(object):

    def __init__(self):
        """ 初始化服务器的各项内容 """
         # 1. 创建监听套接字
        self.tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        #此处可以加一句,资源立即释放的语句(略)

        # 2.绑定信息
        local_ip = ""
        local_port = 5000
        local_addr = (local_ip, local_port)
        self.tcp_socket_server.bind(local_addr)

        # 3.设置为监听模式
        self.tcp_socket_server.listen(128)



    # 给新连接进来的客户端返回一个html页面
    def communicate(self, new_socket, client_addr):
        # (1).将收到的客户端请求先解码,以便后续代码中提取想要的具体请求页面
        request = new_socket.recv(1024).decode('utf-8')
        print(request,"  [from:{}".format(client_addr))
        # (2).将已经解码变为字符串的request进行切割
        request_lines = request.splitlines()
        # print(request_lines)
        # (3).从列表中取得想要的东西,浏览器想要的文件名
        # GET /index.html HTTP/1.1
        # 这个正则又看不懂了。得查。
        # ^ :不是后面的字符
        # 把需要的用括号括起来
        # 防止没有flie_name ,先设为空字符串
        file_name = ""
        print(">>>>>>",request_lines)
        if request_lines:
            ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
            if ret:
                file_name = ret.group(1)
                print("*"*50, file_name)
                if file_name == '/':
                    file_name = '/index.html' 
        
        # 返回http格式的数据,给浏览器
        # 如果请求的资源不是以.py结尾,那么就认为是静态资源(html/css/js/png,JPG等)
        if not file_name.endswith('.py'):  
            # 打开请求的文件, 由于不一定有文件,所以用try except
            try:
                f = open("./static" + file_name, 'rb')
            except:
                response = "HTTP/1.1 404 NOT FOUND\r\n"
                response += "\r\n"
                response += "-----no page-----"
                new_socket.send(response.encode('utf-8'))
            else:
                html_content = f.read()
                f.close()

                # 准备要发送给浏览器的数据
                response = "HTTP/1.1 200 ok\r\n"
                response += "\r\n"
                new_socket.send(response.encode('utf-8'))  # 发送head
                new_socket.send(html_content)                   # 
        else:
            # 如果是以.py结尾,那么就认为是动态资源的请求
            env = dict()
            env['PATH_INFO'] = file_name
            body = mini_frame.application(env, self.set_response_header)
            
            header = "HTTP/1.1 %s \r\n" % self.status
            for temp in self.headers:
                header += "%s:%s\r\n"%(temp[0], temp[1])
            header += "\r\n"
            
            response = header + body
            #发送response给浏览器
            new_socket.send(response.encode('utf-8'))
        
        new_socket.close()

    def set_response_header(self, status, headers):
        self.status = status
        self.headers = [('server', 'mini_web v8.8')]
        self.headers += headers


    # 充当http server
    def fun_forever(self):
       
        # 4.准备接客
        while True:
            print("等待连接...")
            # (1) accept等待连接,等待到连接后返回新创建的套接字和连接进来的客户端地址
            new_socket, client_addr = self.tcp_socket_server.accept()
            # (2) (使用多进程的方式)调用communicate(返回给连接进来的客户端一个html页面)
            p = multiprocessing.Process(target=self.communicate, args=(new_socket, client_addr))
            p.start()

            # 注!为什么这里要用new_socket.close(),因为在用多进程去实现时,子进程是复制了父进程的资源
            new_socket.close()
        # 6.正常的程序流程要关闭套接字
        self.tcp_socket_server.close()

def main():
    """ 控制整体, 创建一个web服务器对象,然后调用这个对象的run_forever方法运行 """
    wsgiserver = WSGIServer()
    wsgiserver.fun_forever()

if __name__ == "__main__":
    main()

mini_frame.py

def login():
    return "login!"


def index():
    with open("./templates/index.html", 'r') as ref:
        return ref.read() 

def introduce():
    with open("./templates/introduce.html", 'r') as ref:
        return ref.read()

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])

    file_name = environ["PATH_INFO"]

    if file_name == '/login.py':
        return login()
    elif file_name == '/index.py':
        return index()
    elif file_name == '/introduce.py':
        return introduce()
    else:
        return "no page!"

3.展示

Python-web:web服务器+动态资源‘框架’1

小结

理解这个,有助于下一步flask框架的学习。

相关标签: Python web