Web应用流程
1. 协议
TCP:不断开
Http:无状态、短连接(因此Web应用绝大多数都是Http协议)
请求:
请求头 + \r\n\r\n
+ 请求体
响应:
响应头 + \r\n\r\n
+ 响应体(浏览器渲染)
2. 客户端与服务端
浏览器(socket客户端)
- 输入url,DNS解析获得对应域名(
ping www.cnblogs.com
可以获得对应ip)
sk.socket()
sk.connect((ip,端口))
sk.send("我想要...")
- 接收服务器数据
- 连接断开
网站(socket服务端)
监听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(): 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(' ') client.send(b"HTTP/1.1 200 OK\r\n\r\n") func_name = None for item in routes(): 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 = 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