zoukankan      html  css  js  c++  java
  • web开发之http和wsgi

    web开发也就是前端和后端,首先理解一下前后端分离技术,其实说的后端代码和前端代码分割开来。不然不利于前端和后端分别开发。

    web开发

    CS即客户端、服务端编程。传统的socket开发。

    客户端、服务端之间需要使用socket,约定协议,版本(往往使用的协议是TCP或者UDP),指定地址和端口,就可以通信了。客服端、服务端传输数据,数据可以有一定的格式,双方必须先约定好。

    BS编程,即Brower、Server开发。

    brower浏览器,是一种特殊的客户端,支持http(s)协议,能够通过URL向服务器发起请求,等待服务器返回HTML等数据,并在浏览器内可视化展示的程序。

    SERVER,支持http协议,能够接受众多客户端发起的http协议请求,经过处理,将HTML等数据返回给浏览器。

    本质上来说,BS是一种特殊的CS,即客户端必须是一种支持http协议且能解析并渲染html的软件,服务端必须是能够接受多客户端http访问的服务器软件。

    http协议底层是基于tcp协议实现。

    BS开发分为两端开发。

    客户端开发——或称前端开发。HTML(控制格式),css(控制样式),JavaScript等。

    服务端开发, python有WSGI,django,flask,tornado等。

    http协议

    http协议是无状态协议。同一个客户端的两次请求之间并没有任何关系,从服务端角度来说,它不知道这两个请求来自同一个客户端。

    cookie

    键值对信息。浏览器每发起一次请求,都会把cookie信息发给服务器端。它是一种客户端,服务器端传递数据的技术。服务器端通过判断这些信息,来确定这次请求是否和之前的请求有关联。一般来说cookie信息是在服务器端生成,返回给客户端的。当然,客户端也可以自己设置cookie信息。

    cookie有非常大的安全问题。一般来说,浏览器每次都会发送cookie给服务器,但是第一次没有。

    URL组成

    URL可以说是地址,uniform resource locator统一资源定位符,每一个链接指向一个资源供客户端访问。例如通过下面的URL访问网页,http://www.xpc.com/pathon/index.html/?id=5&name=python,访问静态资源时,通过上面这个URL访问的是网站的某个路径下的index.html文件,而这个文件对应磁盘上的真实的文件。就会从这个磁盘上读取这个文件,并把这个文件的内容发回给浏览器端。

    URL并不一定对应静态的资源,也可以是动态的资源。

    scheme模式、协议:

    http,ftp,https,file,mailto等。

    host:port

    www.xpc.com:80,80端口是是默认端口可以不写,域名会使用dns解析,域名会解析成IP地址才能使用。实际上会对解析后返回的IP的tcp的80端口发起访问。

    /path/to/resource,path是指向资源的路径。

    ?key1=value1@key2=value2,这是query string,查询字符串,问好分割,后面key=value形式,且使用&符号分割。

    HTTP消息

    消息分为Request,Response

    Request:浏览器向服务器发起的请求。

    Response:服务器对客户端请求的响应。

    请求和响应都是由请求行,header消息报头,body消息正文组成。

    请求

    请求消息行:请求方法method 请求路径 协议版本CRLF(回车换行)

     请求方法method

    GET:请求获取URL对应的资源。get方法将请求的数据都放在了headers里面。如果带body,请求头后面要带两个回车换行。

    POST:提交数据至服务器端

    HEAD:和get类似,不过不返回消息正文。(一般用于测试)

    常见传递信息的方式。

    1.GET方法使用query string

     通过查询字符串在URL中传递参数。

    2.POST方法提交数据

    上面的age = 5&weight=80&height = 170也是参数,查询字符串也是参数。 

    3.url中本身就包含着信息。

    在URL中本身已经传递出信息了。同样的URL,方法不同,意义不同。比如代表获取还是提交数据。

     响应

    响应消息行:协议版本 状态码 消息描述CRLF

     状态码

    nginx必须会。 

    无状态,有连接和短连接

    无状态,指的是服务器无法知道2次请求之间的联系,即使是前后2次同一个浏览器也没有任何数据能够判断出是同一个浏览器的请求,后来可以通过cookie,session来判断。

    有连接:是因为它基于tcp协议,是面向连接的,需要三次握手,4次断开。

    短连接:http1.1之前,都是一个请求一个连接,而tcp的连接创建销毁成本高,对服务器有很大的影响,所以,从http1.1开始,支持keep-alive,默认也开启,一个连接打开后,会保持一段时间(可设置),浏览器再访问该服务器就使用这个tcp连接,减轻了服务器压力,提高了效率。

    http推荐图书《http权威指南》

    WSGI

    wsgi服务器是tcp的。environ是一个字典。 

    WSGI主要规定了服务器端和应用程序间的接口。

    WSGI服务器——wsgiref

    wsgiref这是一个wsgi参考实现库

    wsgiref.smple_server模块实现一个简单的WSGI http服务器。

     

    from wsgiref.util import setup_testing_defaults
    from wsgiref.simple_server import make_server
    
    def simple_app(environ, start_response):
        setup_testing_defaults(environ)
    
        status = '200 OK'
        headers = [('Content-type', 'text/plain; charset=utf-8')]
    
        start_response(status, headers)
    
        ret = [("%s: %s
    " % (key, value)).encode("utf-8")
               for key, value in environ.items()]
        return ret #返回要求可迭代对象,正文就是这个列表的元素,可以是一个元素——字符串。
    
    with make_server('0.0.0.0', 8000, simple_app) as httpd:#创建server,创建的server调用simple_app,请求来了就调用它。
        print("Serving on port 8000...")
        httpd.serve_forever()

    自己按照上面的写一个。

    from wsgiref.simple_server import make_server,demo_app
    
    server = make_server('0.0.0.0',9000,demo_app)#不管发出什么请求,服务器都用demo_app来处理。
    
    server.serve_forever()

    上面的代码运行后,然后在浏览器中输入127.0.0.1:9000后就可以直接返回结果,结果返回可以看到是返回的上面的环境变量。

    看看demo_app的代码。

    def demo_app(environ,start_response):
        from io import StringIO
        stdout = StringIO()
        print("Hello world!", file=stdout)
        print(file=stdout)
        h = sorted(environ.items())
        for k,v in h:
            print(k,'=',repr(v), file=stdout)
        start_response("200 OK", [('Content-Type','text/plain; charset=utf-8')])
        return [stdout.getvalue().encode("utf-8")]

     WSGI服务器的作用

    • 监听HTTP服务端口(tcpserver,默认端口80)
    • 接受浏览器端的http请求并解析封装成environ环境数据。
    • 负责调用应用程序, 将environ和start_response方法传入。
    • 将应用程序响应的正文封装成http响应报文返回浏览器端。

    WSGI APP应用程序端

    1.应用程序应该是一个可调用对象,python中用该是函数,类,实现了__call__方法的类的实例。

    2.同时,这个可调用对象应该接收两个参数。

     3.同时,以上的可调用对象实现,都必须返回一个可迭代对象。

    比如:res_str = b'xpcnanc.com '

     environ和start_response这两个参数名可以是任何合法名,但是一般默认都是这两个名字。应用程序段还有很多其他的规定,这里暂不关心。

    from wsgiref.simple_server import make_server
    
    def simple_app(environ, start_response):
        for k,v in environ.items():
            print(k,v)
        print('+'*30)
    
        status = '200 OK'
        headers = [('Content-type', 'text/plain; charset=utf-8')]
    
        start_response(status, headers)
    
        ret = [("%s: %s
    " % (key, value)).encode("utf-8")
               for key, value in environ.items()]
        return ret #返回要求可迭代对象,正文就是这个列表的元素,可以是一个元素——字符串。
    
    class A:
    
        def __init__(self,name,age):
            pass
        def __call__(self, environ, start_response):
            pass
    
    class B:
        def __init__(self,environ, start_response):
            for k, v in environ.items():
                print(k, v)
            print('+' * 30)
    
            status = '200 OK'
            headers = [('Content-type', 'text/plain; charset=utf-8')]
    
            start_response(status, headers)
    
            ret = [("%s: %s
    " % (key, value)).encode("utf-8")
                   for key, value in environ.items()]
            self.ret = ret
            #return ret  # 返回要求可迭代对象,正文就是这个列表的元素,可以是一个元素——字符串。
        
        def __iter__(self):
            yield from self.ret
    
    #with make_server('0.0.0.0', 8000, A()) as httpd
    #with make_server('0.0.0.0', 8000, B) as httpd
    
    with make_server('0.0.0.0', 8000, simple_app) as httpd:#创建server,创建的server调用simple_app,请求来了就调用它。
        print("Serving on port 8000...")
        httpd.serve_forever()

    environ

    environ是包含http请求信息的dict对象。

     start_response

    它是一个可调用对象,有3个参数,定义如下。

    status是状态码,例如200 OK

    response_headers.是一个元素为二元组的列表,例如[(‘content-Type','text/plain;charset=utf-8')]

    exc_info在错误处理的时候使用

    start_response应该在返回可迭代对象之前调用,因为它返回的是Response Header.返回的可迭代对象是 Response Body。

    服务器端

    服务器程序需要调用符合上述定义的可调用对象APP,传入environ,start_response,APP处理后,返回响应头和可迭代对象的正文,由服务器封装返回浏览器端。

     simple_server只是参考用,不能用于生成。

    到这里即完成了一个简单的web程序开发。

    web服务器

    • 本质上就是一个tcp服务器,监听在特定端口上。
    • 支持http协议,能够将http请求报文进行解析,能够把响应数据进行http协议的报文封装并返回浏览器端。
    • 实现了WSGI协议,该协议约定了和应用程序之间接口。

    APP应用程序

    • 遵从WSGI协议。
    • 本身是一个可调用对象。
    • 调用start_response,返回响应头部。
    • 返回包含正文的可迭代对象。
     
     
  • 相关阅读:
    Team Queue(队列)
    括号匹配(栈+贪心)
    string操作
    树状数组优化+dp
    最短路径变形(最大值的最小值)
    D. Ehab the Xorcist(异或和关系)
    2019 计蒜之道 第五场 A(set的应用)
    2019 计蒜之道 第三场 D(找规律+欧拉降幂)
    hdu 3507 Print Article(斜率优化dp入门题)
    oj 26319 最大子序和
  • 原文地址:https://www.cnblogs.com/xpc51/p/12267471.html
Copyright © 2011-2022 走看看