内容提纲
1.Web应用的本质是什么?
我们知道,在互联网时代,当前软件产品的主流形态是Web应用。思考我们平时通过浏览器上网的过程,如下图:
- Web应用程序是一种基于B/S(或C/S)架构的网络应用程序,既然是网络应用程序,那么其背后一定是基于socket网络编程来实现的;
- Web应用程序作为一种C/S架构的网络应用程序,其客户端是浏览器(Chrome/IE/Firefox等),服务器端是Web服务器;
- 浏览器与Web服务器之间通信使用的交互语言是HTTP协议(一种应用层协议);
- 综上,我们可以得出:Web应用本质上就是一个基于B/S架构的网络应用程序(使用了socket网络编程),这个程序包含一个socket服务端,一个socket客户端(即我们用户使用的浏览器)。
2. 我们开发一个Web应用程序,开发的到底是什么?
在知道Web应用程序本质上包含一个socket客户端程序和一个socket服务器端程序,那么当我们说要开发一个Web应用程序的时候,无非也就是去开发一个socket客户端程序,和一个socket服务器端程序。
- 开发socket 客户端程序(这些浏览器已经全部实现)
- 如何建立TCP连接(Socket编程)
- 如何封装HTTP请求包?(HTTP 协议相关)
- 如何处理解析服务器返回的HTTP响应包?(HTTP 协议相关)
- 解析HTTP响应包体数据,渲染成用户所看到的界面(能够解析HTML、CSS、JS等)
- 开发socket服务器程序?
- 如何建立TCP连接(Socket编程)
- 如何封装HTTP响应包(HTTP协议相关)
- 如何处理不同的请求,返回不同的数据(业务逻辑)
- 区分Web应用程序和Web服务器程序
3. 什么是Web框架?
通过上述分析,我们得出一个Socket服务器端程序包含两部分:Web服务器程序和Web应用程序。当把socket服务端程序分看做两个部分的时候,一个问题出现了,就是两者之间如何协调工作?自然而然,我们想到的解决方案是指定一个统一的接口标准,大家遵循这个规范即可。这个标准就是WSGI(Web Server Gateway Interface)。
- Web 服务器程序负责对socket 进行封装,实现传输层TCP服务,应用层HTTP协议数据包的封装和解析。
- Web应用程序负责具体的业务逻辑处理。
为了提高开发效率和规范,将许多通用的操作封装起来,就出现了许多半成品的Web应用程序(我们称之为Web框架)。
4.自己动手写一个Web框架(使用socket)?
#coding:utf-8
import socket
def do_request(connection):
buffer = connection.recv(1024)
connection.send(b"HTTP /1.1 200 OK\r\n\r\n")
connection.send(b"Hello World")
def server():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 8080))
sock.listen(5)
while True:
connection, address = sock.accept()
do_request(connection)
if __name__ == '__main__':
server()
5.增加功能:如何实现不同的请求URL,响应不同的数据?
5.1 版本一(初级版本)
#coding:utf-8
import socket
def do_request(connection):
buffer = connection.recv(1024)
data = str(buffer, encoding="utf8") # 把收到的字节类型的数据转换成字符串
datas = data.split("\r\n") # 按\r\n分割
print(datas[0]) # 打印请求行
url = datas[0].split()[1] # 拿到url地址
connection.send(b"HTTP /1.1 200 OK\r\n\r\n")
if url == "/login/":
response = b"login"
elif url == "/index/":
response = b"index"
else:
response = b"404 not found"
connection.send(response)
connection.close()
def server():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 8080))
sock.listen(5)
while True:
connection, address = sock.accept()
do_request(connection)
if __name__ == '__main__':
server()
5.2 版本二(函数初级版本)
- 不同的url,需要不同的业务处理,因此可以将对具体url的处理封装成函数。
#coding:utf-8
import socket
def do_request(connection):
buffer = connection.recv(1024)
data = str(buffer, encoding="utf8") # 把收到的字节类型的数据转换成字符串
datas = data.split("\r\n") # 按\r\n分割
print(datas[0]) # 打印请求行
url = datas[0].split()[1] # 拿到url地址
connection.send(b"HTTP /1.1 200 OK\r\n\r\n")
if url == "/login/":
response = b"login"
elif url == "/index/":
response = b"index"
else:
response = b"404 not found"
connection.send(response)
connection.close()
def server