zoukankan      html  css  js  c++  java
  • web框架

    一.导读

    1.web应用:运行在浏览器上的应用。

    2.c/s  b/s 架构:

    client/server:客户端/服务器架构,C++

    brower/server:浏览器/服务器架构,Java,Python

    3.python  web框架:

    Django:socket用的是wsgiref,页面路由用的自己写的,模板渲染用的自己写的,特点:功能全面。

    Flask:socket用的是第三方,页面路由用的自己写的,模板渲染用的自己写的,特点:小而轻。

    Tornado:socket用的是自己写的,页面路由用的自己写的,模板渲染用的自己写的,特点:支持高并发。

    二.HTTP协议

    1.什么是http协议?

    HTTP(HyperText Transport Protocol)指的是超文本传输协议,它是基于TCP/IP协议基础上的应用层协议,底层实现还是socket,它是基于请求-响应模式:通信一定是从客户端开始,服务器端接收到客户端一定会做出对应响应。

    无连接:一次连接只完成一次请求-响应,请求-响应完毕后会立即断开连接。

    无状态:协议不对任何一次通信状态和任何数据进行保存。

    2.http工作原理(事务)

    一次http操作称之为一个事务,工作过程可以分为四步:

    1.客户端与服务器建立连接;

    2.客户端发生一个http协议指定格式的请求;

    3.服务器端接收请求后,响应一个http协议指定格式的响应;

    4.客户端将服务器的响应显示展现给用户。

    import socket
    PORT = 9999
    server = socket.socket()
    server.bind(('127.0.0.1', PORT))
    server.listen(5)
    print("服务器启动:http://127.0.0.1:%s" % PORT)
    
    while True:
        brower, addr = server.accept()
        req_data = brower.recv(1024).decode('utf-8')
        # print(req_data)
    
        # 响应报文
        # 遵循http协议返回数据:响应行 响应头 响应体
        brower.send(b'HTTP/1.1 200 OK
    ')  # 响应行(必须),以
    结束
        brower.send(b'Content-type:text/html
    ')  # 响应头(可选),服务于响应头
        brower.send(b'
    ')  # 响应规则与响应体内容之间还需要一个
    进行分割
        brower.send(b'hahaha')  # 响应体(可选)
        brower.send(b'<h1>hello world</h1>')
        
        brower.close()  # 必须关闭每一次的连接
    
    
    # 请求报文
    '''
    GET / HTTP/1.1
    Host: 127.0.0.1:9999
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9
    
    
    GET /favicon.ico HTTP/1.1  # /favicon.ico指的是页面头的图标
    Host: 127.0.0.1:9999
    Connection: keep-alive
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36
    Accept: image/webp,image/apng,image/*,*/*;q=0.8
    Referer: http://127.0.0.1:9999/
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9
    '''
    基础b/s架构

    3.http处理响应

    import socket
    PORT = 9999
    server = socket.socket()
    server.bind(('127.0.0.1', PORT))
    server.listen(5)
    print("服务器启动:http://127.0.0.1:%s" % PORT)
    
    
    def index():
        pass
    
    
    def login():
        pass
    
    
    def ico():
        with open('1.jpg', 'rb') as f:
            data = f.read()
        return data
        
    
    func_dic = {
        '/': index,
        '/index': index,
        '/login': login,
        '/favicon.ico': ico
    }
    
    while True:
        brower, addr = server.accept()
        req_data = brower.recv(1024).decode('utf-8')
        # print(req_data)
    
        # 响应报文
        # 遵循http协议返回数据:响应行 响应头 响应体
        brower.send(b'HTTP/1.1 200 OK
    ')  # 响应行(必须),以
    结束
        brower.send(b'Content-type:text/html
    ')  # 响应头(可选),服务于响应头
        brower.send(b'
    ')  # 响应规则与响应体内容之间还需要一个
    进行分割
    
        # GET / HTTP/1.1
        # GET /favicon.ico HTTP/1.1
        path = req_data.split('
    ')[0].split(' ')[1]  # 请求路径
        # 根据路径,处理不同的请求方法
        if path in func_dic:
            res_dic = func_dic[path]()
        res_dic = b'<h1 style="text-align: center">404</h>'
        brower.send(res_dic)  # 响应体(可选)
        brower.close()  # 必须关闭每一次的连接
    请求分配

    基于上面的基础b/s架构,可以根据请求http协议数据,解析出请求路径,根据具体路径完成业务逻辑,的方法,完成对应的响应。

    1.由于业务逻辑会不断的增加,所以业务逻辑要进行分层单独处理;

    2.路径与业务处理方法对应关系也会越来越多,越来越复杂,也可以分离单独处理;

    3.自定义服务器功能不健全,稳定性差,可以选择第三方

    server.py
    
    import socket
    from wsgi协议.urls import url_dic
    PORT = 9999
    server = socket.socket()
    server.bind(('127.0.0.1', PORT))
    server.listen(5)
    print("服务器启动:http://127.0.0.1:%s" % PORT)
    
    while True:
        brower, addr = server.accept()
        req_data = brower.recv(1024).decode('utf-8')
        # print(req_data)
    
        # 响应报文
        # 遵循http协议返回数据:响应行 响应头 响应体
        brower.send(b'HTTP/1.1 200 OK
    ')  # 响应行(必须),以
    结束
        brower.send(b'Content-type:text/html
    ')  # 响应头(可选),服务于响应头
        brower.send(b'
    ')  # 响应规则与响应体内容之间还需要一个
    进行分割
    
        # GET / HTTP/1.1
        # GET /favicon.ico HTTP/1.1
        url = req_data.split('
    ')[0].split(' ')[1]  # 请求路径
        # 根据路径,处理不同的请求方法
        if url in url_dic:
            res_dic = url_dic[url]()
        res_dic = b'<h1 style="text-align: center">404</h>'  # 响应错误时返回404
        brower.send(res_dic)  # 响应体(可选)
        brower.close()  # 必须关闭每一次的连接
    
    
    urls.py
    
    from wsgi协议.views import *
    
    url_dic = {
        '/': index,
        '/index': index,
        '/login': login,
        '/favicon.ico': ico
    }
    
    
    views.py
    
    def index():
        pass
    
    
    def login():
        pass
    
    
    def ico():
        with open('1.jpg', 'rb') as f:
            data = f.read()
        return data
    分层请求分配处理

    4.状态码

    # 1打头:消息通知
    # 2打头:请求成功
    # 3打头:重定向
    # 4打头:客户端错误
    # 5打头:服务器端错误

    三.WSGI协议

    利用第三方wsgiref服务器完成http请求-响应:

    通过wsgiref模块创建server时,有三个参数分别是:Host,Port,app,其中app时一个回调函数,该回调函数有两个参数:environ和response;environ是一个字典,请求的数据都被解析在该字典中,用response来规定http响应的结果。

    server.py
    
    from wsgiref import simple_server
    from wsgi协议.urls import url_dic
    PORT = 8888
    
    
    # 回调函数
    def app(environ, response):
        # 请求的数据都被解析在environ字典中
        # 请求方式的key:REQUEST_METHOD  # 'REQUEST_METHOD': 'GET'
        # 请求的路径的key:PATH_INFO  # 'PATH_INFO': '/'
        print(environ)
        # 用response来规定http响应的结果
        response('200 OK', [('Content-type', 'text/html')])
    
        # 数据的获取
    
        # 解析给key,得到数据
        method = environ['REQUEST_METHOD']  # 请求方法
        res_dic = {}
        url = ''
        if method == 'GET':
            url = environ['PATH_INFO']  # 请求路径
            # 在GET方法中:数据在environ中的QUERY_STRING对应的value
            res_str = environ['QUERY_STRING']
            if res_str:
                res_list = res_str.split('&')
                for i in res_list:
                    data_list = i.split('=')
                    res_dic[data_list[0]] = data_list[1]
        elif method == 'POST':  # 在POST方法中:数据存放的io流'wsgi.input': <_io.BufferedReader name=552>;数据长度'CONTENT_LENGTH': '40'
            length = int(environ['CONTENT_LENGTH'])
            if length == 0:
                return
            res_str = environ['wsgi.input'].read(length).decode('utf-8')
    
            res_list = res_str.split('&')
    
            for i in res_list:
                data_list = i.split('=')
                if i is res_list[-1]:
                    url = '/' + data_list[0]
                    # print(url)
                    continue
                res_dic[data_list[0]] = data_list[1]
            # print(res_dic)
    
        req_dic = b'<h1 style="text-align: center">404</h1>'
        if url in url_dic:
            req_dic = url_dic[url](res_dic)
    
        # print(res_dic)
    
        # 返回的是装有二进制数据的列表
        return [req_dic]
    
    
    if __name__ == '__main__':
        server = simple_server.make_server('127.0.0.1', PORT, app=app)  # 通过wsgiref创建server
        print('服务器启动:http://127.0.0.1:%s' % PORT)
        # 保持server一直运行
        server.serve_forever()
    
    
    views.py
    
    import pymysql
    from jinja2 import Template
    
    
    def execute(sql, args):
        conn = pymysql.connect(
            host='127.0.0.1',
            port=3306,
            user='root',
            password='root',
            db='db1',
            charset='utf8',
            autocommit=True
        )
        cursor = conn.cursor(pymysql.cursors.DictCursor)
        affect_row = cursor.execute(sql, args=args)
        return affect_row
    
    
    def index(dic):
        pass
    
    
    def login(dic):
        # print(dic)
        name = dic['usr']
        pwd = dic['pwd']
        sql = "select * from user where name=%s and pwd=%s"
        args = [name, pwd]
        row = execute(sql, args)
        with open('login.html', 'rt') as f:
            msg = f.read()
        tem = Template(msg)
        if row:
            res = 'login success'
        else:
            res = 'login failed'
        msg = tem.render(result=res)
        return msg.encode('utf-8')
    
    
    def register(dic):
        pass
    
    
    def ico(dic):
        with open('timg.jpg', 'rb') as f:
            data = f.read()
        return data
    
    login.html
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>title</title>
    </head>
    <body>
        {{ result }}
    </body>
    </html>
    
    urls.py
    
    from wsgi协议.views import *
    
    url_dic = {
        '/': index,
        '/index': index,
        '/login': login,
        '/favicon.ico': ico
    }
    
    deom.html
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="http://127.0.0.1:8888" method="post">
        <input type="text" name="usr">
        <br>
        <input type="password" name="pwd">
        <br>
        <input type="submit" value="login" name="login">
    </form>
    </body>
    </html>
    简单登录功能
  • 相关阅读:
    《浅谈12306核心模型设计思路和架构设计》阅读笔记
    《一路打怪升级,360推荐系统架构演进》阅读笔记
    SOA架构设计的案例分析
    《苏宁易购:商品详情系统架构设计》阅读笔记
    《数据蜂巢架构演进之路》阅读笔记
    洛谷P1005 矩阵取数游戏
    LOJ#6277. 数列分块入门 1
    洛谷P1879 [USACO06NOV]玉米田Corn Fields
    洛谷P1072 Hankson 的趣味题
    洛谷P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm
  • 原文地址:https://www.cnblogs.com/wangke0917/p/10432607.html
Copyright © 2011-2022 走看看