WSGI协议---02

为什么要说WSGI

自己写的服务器是支持不了高并发的,因此一般是用现成的比较优秀的服务器,一般有apache,nginx等等,但是用别人写的服务器是可能像自己写的一样直接import的,可能我们拿到的就是汇编或者二进制代码,那么怎么让别人的服务器支持自己写的前端页面呢,只要我们遵循WSGI协议就可以。

WSGI协议流程

浏览器请求http协议动态资源,web服务器调用一个属性,一般来说这个属性是application(),我们在自己的应用程序框架里面也要协商application函数,里面两个参数,一个字典一个函数指针。然后应用程序框架里面通过引用调用的web服务器的方法,设置返回的状态和头信息(这里的状态其实就是404或者200 OK)。web服务器调用返回,此时web服务器保存了刚刚设置的信息。应用程序框架生成动态页面的body信息。把生成的信息返回给web服务器调用。简而言之,wsgi是将python服务器程序连接到web服务器的通用协议uwsgi是独立的实现了wsgi协议的服务器。

自写的服务器,解耦合

关键代码
body=test.application(file_name) #接耦合
server完整代码
import socket
import re
import multiprocessing
import time
import test


class WSGIserver(object):

    def __init__(self):
        # 1. 创建套接字
        self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        # 2. 绑定
        self.tcp_server_socket.bind(("172.16.70.64", 7890))

        # 3. 变为监听套接字
        self.tcp_server_socket.listen(128)

    def service_client(self, new_socket):
        """为这个客户端返回数据"""

        # 1. 接收浏览器发送过来的请求 ,即http请求
        # GET / HTTP/1.1
        # .....
        request = new_socket.recv(1024).decode("utf-8")
        # print(">>>"*50)
        # print(request)

        request_lines = request.splitlines()
        print("")
        print(">" * 20)
        print(request_lines)

        # GET /index.html HTTP/1.1
        # get post put del
        file_name = ""
        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"

        # 2. 返回http格式的数据,给浏览器
        # 如果请求的资源不是.py结尾的就认为是静态资源
        if not file_name.endswith(".py"):
            try:
                f = open("../html" + file_name, "rb")
            except:
                response = "HTTP/1.1 404 NOT FOUND\r\n"
                response += "\r\n"
                response += "------file not found-----"
                new_socket.send(response.encode("utf-8"))
            else:
                html_content = f.read()
                f.close()
                # 2.1 准备发送给浏览器的数据---header
                response = "HTTP/1.1 200 OK\r\n"
                response += "\r\n"
                # 2.2 准备发送给浏览器的数据---boy
                # response += "hahahhah"

                # 将response header发送给浏览器
                new_socket.send(response.encode("utf-8"))
                # 将response body发送给浏览器
                new_socket.send(html_content)
        else:
            # 如果是已.py结尾那么就认为是动态请求
            header="HTTP/1.1 200 OK\r\n"
            header+="\r\n"
            
            body=test.application(file_name) #接耦合
            #body=test.login()

            response=header+body

            new_socket.send(response.encode("utf-8"))

        # 关闭套接
        new_socket.close()

    def runforever(self):
        """用来完成整体的控制"""

        while True:
            # 4. 等待新客户端的链接
            new_socket, client_addr = self.tcp_server_socket.accept()

            # 开一个进程
            p = multiprocessing.Process(target=self.service_client, args=(new_socket,))

            p.start()

            new_socket.close()

            # # 5. 为这个客户端服务
            # service_client(new_socket)

        # 关闭监听套接字
        tcp_server_socket.close()


def main():
    """
    控制整体,创建一个web服务器对象,然后调用这个对象的run方法
    :return:None
    """
    wsgi_server = WSGIserver()
    wsgi_server.runforever()


if __name__ == "__main__":
    main()

test应用程序框架完整代码
import time

def login():
    return "welcome to our website ----time is %s "%time.time()

def register():
    return "登录"

def profile():
    return "个人主页"

def application(file_name):
    if file_name=="/log_in.py":
        login()
    elif file_name=="/register.py":
        register()
    elif file_name=="/profile.py":
        profile()
    else:
        return "没有发现你的主页"

** 完整程序已上传git,拉至最后查看地址 **

自写服务器实现WSGI协议支持

server文件改动

       else:

            env=dict()#空字典
            body=test.application(env,self.set_response_header) #接耦合

            # 如果是已.py结尾那么就认为是动态请求
            header = "HTTP/1.1 200 OK %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

            new_socket.send(response.encode("utf-8"))

        # 关闭套接
        new_socket.close()

    def set_response_header(self,status ,headers):
        self.status=status
        self.headers=headers
test应用程序框架改动
def application(environ,start_response):
    start_response("200 OK",[('Content-Type','text/html')])
    return 'Hello World!'

** 完整程序已上传git,拉至最后查看地址 **

encode方式

在这里插入图片描述

test文件
def application(environ,start_response):
    start_response("200 OK",[('Content-Type','text/html;charset=utf-8')])
    return 'Hello World!我爱你中国'

application函数的字典参数使用

用字典去存file_name,test里面读取字典,显示相应信息

server文件改动
 else:

            env=dict()#空字典
            env['PATH_INFO']=file_name
            body=test.application(env,self.set_response_header) #接耦合

            # 如果是已.py结尾那么就认为是动态请求
            header = "HTTP/1.1 200 OK %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

            new_socket.send(response.encode("utf-8"))

test文件改动

def index():
    return "主页"

def login():
    return "登录"

def application(env,start_response):
    start_response("200 OK",[('Content-Type','text/html;charset=utf-8'),('server','my_web')])
    file_name=env['PATH_INFO']

    if file_name=="/index.py":
        return index()
    elif file_name == "/login.py":
        return login()
    else:

        return 'Hello World!我爱你中国'

在这里插入图片描述

** 完整程序已上传git,拉至最后查看地址 **

author:[email protected]
github: https://github.com/zhangyuespec/mini_web

猜你喜欢

转载自blog.csdn.net/qq_34788903/article/details/84668271