Web应用流程

1. 协议

TCP:不断开

Http:无状态、短连接(因此Web应用绝大多数都是Http协议)

​ 请求:

​ 请求头 + \r\n\r\n + 请求体

​ 响应:

​ 响应头 + \r\n\r\n + 响应体(浏览器渲染)

2. 客户端与服务端

浏览器(socket客户端)

  1. 输入url,DNS解析获得对应域名(ping www.cnblogs.com可以获得对应ip)

sk.socket()

sk.connect((ip,端口))

sk.send("我想要...")

  1. 接收服务器数据
  2. 连接断开

网站(socket服务端)

  1. 监听ip和端口(

    ​ while True:

    ​ 用户 = 等待用户连接

    ​ 3. 收到我想要...

    ​ 4. 响应(根据不同url响应不同的函数<即路由系统>,通过模板引擎渲染,将html模板内部填充自己的数据,返回字符串)

    ​ 用户断开

3. 服务器端本质

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import socket

def handle_request(client):
buf = client.recv(1024)
client.send(b"HTTP/1.1 200 OK\r\n\r\n")
client.send(b"Hello, Dhy")

def main():
sock = socket.socket()
sock.bind(('127.0.0.1',8080)) # 绑定端口
sock.listen(5) # 最大监听数

while True:
connection, address = sock.accept()
handle_request(connection)
connection.close()

if __name__ == '__main__':
main()

对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。

WSGI(Web Server Gateway Interface)是一种规范,它定义了使用python编写的web app与web server之间接口格式,实现web app与web server间的解耦。

4. 静态动态网页

一个基础的静态网页的实现:传回客户端的数据变为html的字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import socket

def index():
with open('index.html','rb') as f:
data = f.read()
return data

def login():
with open('login.html','rb') as f:
data = f.read()
return data

def routes(): # url和函数的对应 --> 路由系统
urlpatterns = (
('/index/',index),
('/login/',login),
)
return urlpatterns

def handle_request(client):
buf = str(client.recv(8096), encoding='utf-8')
headers, body = buf.split('\r\n\r\n')
temp_list = headers.split('\r\n')
method, url, protocal = temp_list[0].split(' ') # 请求方法,url,协议
client.send(b"HTTP/1.1 200 OK\r\n\r\n")
func_name = None
for item in routes(): # 遍历url_patterns
if item[0] == url:
func_name = item[1]
break
if func_name:
client.send(func_name())
else:
client.send(b'404 not found')

def main():
sock = socket.socket()
sock.bind(('127.0.0.1',8080)) # 绑定端口
sock.listen(5) # 最大监听数

while True:
print ("Serving HTTP on port 8000...")
connection, address = sock.accept()
handle_request(connection)
connection.close()

if __name__ == '__main__':
main()

问题:如何给用户返回动态内容?

  • 自定义一套特殊的语法,从数据库取数据,进行替换
  • 使用开源工具jinja2,遵循其指定语法
1
2
3
from jinja2 import Template
template = Template(data) # data -> 渲染前
data = template.render(...=...) # 把模板中需要用到的变量传入

5. Web框架分类

自己建站,需要:

​ a. socket服务端

​ b. 根据不同url响应不同的函数(即路由系统)

​ c. 通过模板引擎渲染,将html模板内部填充自己的数据,返回字符串

Web框架大致可分为:

  • 实现了a,b,c → Tornado
  • [第三方a],实现b,c → Django [ python库wsgiref 提供socket支持]
  • [第三方a],实现b,[第三方c] → flask