web应用+250斗笔式模拟框架

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请求才会有请求体)

换行:\r\n     请求头与请求体之间用\r\n\r\n

 响应协议格式:

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

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

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

换行:\r\n     响应头与响应体之间用\r\n\r\n

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\r\n\r\n".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('\r\n\r\n')
37         temp_list = headers.split('\r\n')
38         method, url, protocal = temp_list[0].split(' ')
39         conn.send(b"HTTP/1.1 200 OK\r\n\r\n")
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>[email protected]</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('\r\n\r\n')
63         temp_list = headers.split('\r\n')
64         method, url, protocal = temp_list[0].split(' ')
65         conn.send(b"HTTP/1.1 200 OK\r\n\r\n")
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]---------------------------->warkzeug--->Flask

                

猜你喜欢

转载自www.cnblogs.com/Alexephor/p/11240100.html