web框架本质
所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端。 这样我们就可以自己实现Web框架了。
import socketsk = socket.socket()sk.bind(("127.0.0.1", 80))sk.listen()while True: conn, addr = sk.accept() data = conn.recv(8096) print(data) # 将浏览器发来的消息打印出来 conn.send(b"OK") conn.close()访问127.0.0.1:80 页面能显示ok字样 可以conn.send(b"OK")这种形式
GET / HTTP/1.1Host: 127.0.0.1Connection: keep-aliveCache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: Hm_lvt_ba7c84ce230944c13900faeba642b2b4=1528700314; Hm_lpvt_ba7c84ce230944c13900faeba642b2b4=1528701771
非http版本的response header 信息 有点晕了,为什么是一样的呢?
服务端打印的信息(浏览器发过来的信息) b'GET /index HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: Hm_lvt_ba7c84ce230944c13900faeba642b2b4=1528700314; Hm_lpvt_ba7c84ce230944c13900faeba642b2b4=1528700435\r\n\r\n'b'GET /favicon.ico HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: keep-alive\r\nPragma: no-cache\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nReferer: http://127.0.0.1/index\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: Hm_lvt_ba7c84ce230944c13900faeba642b2b4=1528700314; Hm_lpvt_ba7c84ce230944c13900faeba642b2b4=1528700435\r\n\r\n'第一段有请求方法,用户访问页面的路径, 只有str能被split,bytes类型不能
import socketsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.bind(('127.0.0.1', 8000))sock.listen()while True: conn, addr = sock.accept() data = conn.recv(8096) # 给回复的消息加上响应状态行 conn.send(b"HTTP/1.1 200 OK\r\n\r\n") conn.send(b"OK") conn.close()http版
GET / HTTP/1.1Host: 127.0.0.1:8000Connection: keep-aliveCache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8Accept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.9Cookie: Hm_lvt_ba7c84ce230944c13900faeba642b2b4=1528700314; Hm_lpvt_ba7c84ce230944c13900faeba642b2b4=1528701753 http版本的response header 信息
b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8000\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: Hm_lvt_ba7c84ce230944c13900faeba642b2b4=1528700314; Hm_lpvt_ba7c84ce230944c13900faeba642b2b4=1528702117\r\n\r\n'
b'GET /favicon.ico HTTP/1.1\r\nHost: 127.0.0.1:8000\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nReferer: http://127.0.0.1:8000/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: Hm_lvt_ba7c84ce230944c13900faeba642b2b4=1528700314; Hm_lpvt_ba7c84ce230944c13900faeba642b2b4=1528702117\r\n\r\n'
返回具体的动态的HTML页面+函数进阶版
"""根据URL中不同的路径返回不同的内容--函数进阶版返回HTML页面让网页动态起来"""import socketimport timesk = socket.socket()sk.bind(("127.0.0.1", 8080)) # 绑定IP和端口sk.listen() # 监听# 将返回不同的内容部分封装成函数def index(url): with open("index.html", "r", encoding="utf8") as f: s = f.read() now = str(time.time()) s = s.replace("@@oo@@", now) # 在网页中定义好特殊符号,用动态的数据去替换提前定义好的特殊符号 return bytes(s, encoding="utf8")def home(url): with open("home.html", "r", encoding="utf8") as f: s = f.read() return bytes(s, encoding="utf8")# 定义一个url和实际要执行的函数的对应关系list1 = [ ("/index/", index), ("/home/", home),]while 1: # 等待连接 conn, add = sk.accept() data = conn.recv(8096) # 接收客户端发来的消息 # 从data中取到路径 data = str(data, encoding="utf8") # 把收到的字节类型的数据转换成字符串 # 按\r\n分割 data1 = data.split("\r\n")[0] url = data1.split()[1] # url是我们从浏览器发过来的消息中分离出的访问路径 conn.send(b'HTTP/1.1 200 OK\r\n\r\n') # 因为要遵循HTTP协议,所以回复的消息也要加状态行 # 根据不同的路径返回不同内容 func = None # 定义一个保存将要执行的函数名的变量 for i in list1: if i[0] == url: func = i[1] break if func: response = func(url) else: response = b"404 not found!" # 返回具体的响应消息 conn.send(response) conn.close()