zoukankan      html  css  js  c++  java
  • web应用+250斗笔式模拟框架(socket、pymysql、jinja2)

    http协议简介

      HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于万维网(WWW:World Wide Web )服务器与本地浏览器之间传输超文本的传送协议。

    HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。

    http协议特性

    (1) 基于TCP/IP

      http协议是基于TCP/IP协议之上的应用层协议

    (2) 基于请求-响应模式

      HTTP协议规定,请求从客户端发出,最后服务器端响应该请求并 返回。换句话说,肯定是先从客户端开始建立通信的,服务器端在没有 接收到请求之前不会发送响应

    (3) 无状态保存

       HTTP是一种不保存状态,即无状态(stateless)协议。HTTP协议 自身不对请求和响应之间的通信状态进行保存。也就是说在HTTP这个 级别,协议对于发送过的请求或响应都不做持久化处理。你连接我一次,我响应一次就断开了

    (4)无连接

    无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

    请求协议格式:

    大前提:字符串/字节

    请求首行  请求方式  url   (路径?get请求参数)   协议/版本号

    请求头  key:value

    请求体  数据(只有post请求才会有请求体)

    换行:      请求头与请求体之间用

     响应协议格式:

    响应首行   协议/版本号  状态码  状态码译文

    响应头  Content-Type:text/html  key:value

    响应体  <h1>hello</h>  这才是客服端浏览器上显示的东西

    换行:      响应头与响应体之间用

    web框架本质

      大家应该都晓得,所有web应用,本质上就是一个socket服务端,用户浏览器就是一个socket客服端

      下面简单的模拟socket举个例子

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 
     4 import socket
     5 
     6 
     7 def handle_request(client):
     8     data = client.recv(8096)
     9     print(data.decode('utf8'))
    10     client.send("HTTP/1.1 200 OK
    
    ".encode('utf8'))
    11     client.send("Hello WeiSuoJun".encode('utf8'))
    12 
    13 
    14 def main():
    15     sock = socket.socket()
    16     sock.bind(('localhost', 9999))
    17     sock.listen(5)
    18 
    19     while True:
    20         conn, addr = sock.accept()
    21         handle_request(conn)
    22         conn.close()
    23 
    24 
    25 if __name__ == '__main__':
    26     main()

      后边为了方便的开发,大堆的web框架出来了,但是各种框架开发模式应该有所不同,不管咋样最终要开发出的应用程序都要和服务器配合,才能够给用户提供服务,这样服务器程序就要为不同的框架提供不同的支持,这就意味着一片混乱来了,咋能克服混乱局面,大家商量好这套标准。WSGI就诞生了、一套套规范,定义了一些web app与web server之间接口的格式,主要就是实现两者之间的解耦,Python中标准库提供的独立WSGI服务器叫wsgiref这个模块,本质就是socket服务端。

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 
     4 from wsgiref.simple_server import make_server
     5 
     6 def RunServer(environ, start_response):
     7     print(environ)
     8     start_response('200 OK', [('Content-Type', 'text/html')])
     9     return [bytes('<h1>Hello, WeiSuoJun!</h1>', encoding='utf-8'), ]
    10 
    11 
    12 if __name__ == '__main__':
    13     httpd = make_server('127.0.0.1', 9999, RunServer)
    14     print("Serving HTTP on port 9999...")
    15     httpd.serve_forever()

    environ请求所有相关信息

    基于socket模拟web框架的斗笔行为(web250框架)

      (静态页面)实现的思想:等待用户进来连接,收到请求的数据,对数据(字节转字符串)进行分割,拿到请求url走对应的函数(若没有函数进行匹配就返回404),(暂且还没的视图这么一说),在对应的函数(暂且还没得视图这么一说)里边做打开文件操作,然后返回给用户。
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 
     4 import socket
     5 
     6 
     7 def f1(request):
     8     f = open('index.html', 'rb')
     9     data = f.read()
    10     f.close()
    11     return data
    12 
    13 
    14 def f2(request):
    15     f = open('article.html', 'rb')
    16     data = f.read()
    17     f.close()
    18     return data
    19 
    20 
    21 routers = [
    22     ('/xxxx', f1),
    23     ('/oooo', f2),
    24 ]
    25 
    26 
    27 def run():
    28     sock = socket.socket()
    29     sock.bind(("127.0.0.1", 8080))
    30     sock.listen(5)
    31 
    32     while True:
    33         conn, addr = sock.accept()
    34         data = conn.recv(8096)
    35         data = str(data, encoding='utf8')
    36         headers, bodys = data.split('
    
    ')
    37         temp_list = headers.split('
    ')
    38         method, url, protocal = temp_list[0].split(' ')
    39         conn.send(b"HTTP/1.1 200 OK
    
    ")
    40 
    41         func_name = None
    42         for item in routers:
    43             if item[0] == url:
    44                 func_name = item[1]
    45                 break
    46         if func_name:
    47             response = func_name(data)
    48         else:
    49             response = b"404"
    50 
    51         conn.send(response)
    52 
    53         conn.close()
    54 
    55 
    56 if __name__ == '__main__':
    57     run()
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title></title>
     6 </head>
     7 <body>
     8     <h1>用户登录</h1>
     9 <form action="">
    10     <p><input type="text" placeholder="用户名"></p>
    11     <p><input type="text" placeholder="密码"></p>
    12     <p><input type="submit" value="提交"></p>
    13 </form>
    14 </body>
    15 </html>
    index.html
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title></title>
     6 </head>
     7 <body>
     8     <table border="1">
     9         <thead>
    10             <tr>
    11                 <th>id</th>
    12                 <th>用户名</th>
    13                 <th>邮箱</th>
    14             </tr>
    15         </thead>
    16         <tbody>
    17             <tr>
    18                 <th>1</th>
    19                 <th>@root@</th>
    20                 <th>root@qq.com</th>
    21             </tr>
    22         </tbody>
    23     </table>
    24 </body>
    25 </html>
    article.html

       (动态页面)实现思想:只是在静态的基础上,通过pymysql模块连接数据库,拿到数据然后使用jinja2对模板的渲染,然后返回给用户。

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 
     4 import socket
     5 
     6 
     7 def f1(request):
     8     f = open('index.html', 'rb')
     9     data = f.read()
    10     f.close()
    11     return data
    12 
    13 
    14 def f2(request):
    15     f = open('article.html', 'r', encoding='utf8')
    16     data = f.read()
    17     f.close()
    18     import time
    19     ctime = time.ctime()
    20     data = data.replace('@root@', str(ctime))
    21     return data.encode('utf8')
    22 
    23 
    24 def f3(request):
    25     import pymysql
    26     conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='db2')
    27     cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    28     cursor.execute("select id,name,extra from users")
    29     user_list = cursor.fetchall()
    30     cursor.close()
    31     conn.close()
    32     print(user_list)
    33 
    34     f = open('userinfo.html', 'r', encoding='utf8')
    35     data = f.read()
    36     f.close()
    37 
    38     # 专门来渲染模板
    39     from jinja2 import Template
    40     template = Template(data)
    41     data = template.render(user_list=user_list, name='搞大佬')
    42     print(data)
    43     return data.encode('utf8')
    44 
    45 
    46 routers = [
    47     ('/xxxx', f1),
    48     ('/oooo', f2),
    49     ('/yyyy', f3),
    50 ]
    51 
    52 
    53 def run():
    54     sock = socket.socket()
    55     sock.bind(("127.0.0.1", 13333))
    56     sock.listen(5)
    57 
    58     while True:
    59         conn, addr = sock.accept()
    60         data = conn.recv(4096)
    61         data = str(data, encoding='utf8')
    62         headers, bodys = data.split('
    
    ')
    63         temp_list = headers.split('
    ')
    64         method, url, protocal = temp_list[0].split(' ')
    65         conn.send(b"HTTP/1.1 200 OK
    
    ")
    66 
    67         func_name = None
    68         for item in routers:
    69             if item[0] == url:
    70                 func_name = item[1]
    71                 break
    72         if func_name:
    73             response = func_name(data)
    74         else:
    75             response = b"404"
    76 
    77         conn.send(response)
    78 
    79         conn.close()
    80 
    81 
    82 if __name__ == '__main__':
    83     run()

    index.html与article.html与上边相同

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title></title>
     6 </head>
     7 <body>
     8     <table border="1">
     9         <thead>
    10             <tr>
    11                 <th>id</th>
    12                 <th>用户名</th>
    13                 <th>描述</th>
    14             </tr>
    15         </thead>
    16         <tbody>
    17             {% for row in user_list %}
    18                 <tr>
    19                     <td>{{ row.id }}</td>
    20                     <td>{{ row.name }}</td>
    21                     <td>{{ row.extra }}</td>
    22                 </tr>
    23             {% endfor %}
    24         </tbody>
    25         {{ name }}
    26     </table>
    27 </body>
    28 </html>
    userinfo.html

     实现的效果如图:

       

     总结:

      1.http 无状态 短连接

      2.浏览器(socket客服端)

         网站(socket服务端)

      3.自己搞网站

        a.socket服务端

        b.根据url不同返回不同的内容

          路由系统: url---->函数(视图函数)

        c.字符串返回给用户

          模板引擎渲染:html充当模板(特殊字符)

                 当然自己可以任意数据

                 字符串

      4.web框架

        a,b,c                    ------------------------------->Tornado

        [第三方a],b,c        ------------------------------->wsgiref ---->Django

        [第三方a],b,[第三方c]---------------------------->werkzurg--->Flask

                    

  • 相关阅读:
    托管资源和非托管资源
    无法启动IIS EXpress Web服务器
    SQL 最后一天及第一天
    amchart amline中配置文件amline_settings.xml文件中的配置说明
    SpringBoot添加拦截器
    Lombok插件
    SpringBoot配置访问静态资源
    SpringBoot自动配置原理
    yaml基本格式
    属性文件之SpringBoot注入
  • 原文地址:https://www.cnblogs.com/Alexephor/p/11240100.html
Copyright © 2011-2022 走看看