继续今天的python学习,今天开始正式接触Web方面的知识,这套教程已经不是讲python语法,而是python的应用,按部就班跟着走!!
首先接触“四层模型”,即链路层、网络层、传输层、应用层
链路层:具体的传输工具
网络层:IP,可以理解为地理位置坐标
传输层:如何解决传输数据
应用层:解决要传递什么数据
之前学到的socket就是处理除应用层以外的其他三个层面的问题,而应用层要处理的就是在recv和send之间的问题。
接下来是HTTP的一些请求方式:
GET:获取数据、POST:修改数据、PUT:保存数据、DELETE:删除、OPTION:询问uwuqi的某种支持特性、HEAD:返回报文头。
接下来讲了一种标识符URI(Uniform Resource Identifier),它包含URL(Uniform Resource Locaton)和URN(Uniform Resource Name),从英文单词可以理解,URL标识的是地址,URN标识的是名字。
在浏览器中我们右击审查元素之后,点击上面的Network选项,刷新一下页面会看到很多的数据
在这里要点击view source才能看到这些信息
了解了这些就可以写代码了
import socket
from multiprocessing import Process
import re
import os
import sys
# 设置静态文件根目录
HTML_ROOT_DIR = "./html"
WSGI_PYTHON_DIR = "./wsgipython"
class HTTPserver(object):
""""""
def __init__(self):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# self.server.listen(128)
# 开启服务器
def start(self):
self.server.listen(128)
while True:
cli_socket, cli_address = self.server.accept()
print("%s:%s已连接..." % cli_address)
p = Process(target=self.handle_client, args=(cli_socket,))
p.start()
cli_socket.close()
# WSGI的规定,在这里报文的头,因为后面的application返回的只是报文的body
def start_response(self, status, headers):
# 这是我们自己设置有的要响应的信息
server_headers = [
("Server", "MyServer")
]
# 设置报文头首行
response_headers = "HTTP/1.1 " + status + os.linesep
# 开始添加报文头
for each in server_headers:
response_headers += "%s: %s" % each
response_headers += os.linesep
for header in headers:
response_headers += "%s: %s" % header
response_headers += os.linesep
self.response_headers = response_headers
def handle_client(self, cli_socket):
'''处理客户端请求'''
# 获取用户请求数据
data = cli_socket.recv(1024)
request_header_lines = data.splitlines()
for line in request_header_lines:
print(line.decode("utf-8"))
# 解析请求的报文
request_start_line = request_header_lines[0].decode("utf-8")
# 提取用户请求的文件名
file_name = re.match(r"\w+ +(/[^ ]* )", request_start_line).group(1)
file_name = file_name.strip()
# 默认执行index.html
if "/" == file_name:
file_name = "/index.html"
# 如果文件以py结尾,就是要执行我们的脚本
if file_name.endswith(".py"):
# 执行py文件
m = __import__(file_name[1:-3])
# 这里的env指的是用户需要我们拿过来进行处理的信息
env = {}
# application是WSGI规定的统一的接口,目的是保证调用脚本的通用性
response_body = m.application(env, self.start_response)
response = self.response_headers + os.linesep + response_body
else:
# 读取Html文件
print("文件名:", file_name)
# 打开文件,读取内容
try:
file = open(HTML_ROOT_DIR + file_name, "rb")
except IOError:
response_line = "HTTP/2.0 404 Not Found" + os.linesep
response_headers = "server: JSP3/2.0.14" + os.linesep
response_body = "the file is not found!"
else:
file_data = file.read()
file.close()
# 构造响应函数
response_line = "HTTP/2.0 200 OK" + os.linesep
response_headers = "server: JSP3/2.0.14" + os.linesep
response_body = file_data.decode("utf-8")
response = response_line + response_headers + os.linesep + response_body
cli_socket.send(response.encode("utf-8"))
cli_socket.close()
def bind(self, port):
self.server.bind(("", port))
def main():
# 在这里需要把模块添加到path中才能导入,否则找不到
sys.path.insert(1, WSGI_PYTHON_DIR)
http_server = HTTPserver()
http_server.bind(8000)
http_server.start()
if __name__ == "__main__":
main()
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
模块:m_time.py
import time
def application(env, start_response):
status = "200 OK"
headers = [
("Content-Type", "Text/plain")
]
start_response(status, headers)
return time.ctime()
运行结果:
阅读代码时请看注释,至于WSGI是什么,其实就是一个规定,详情可以在网上查找一下资料。