01.通过socket写一个简单的web框架来理解django
前言
目前,有非常多的Python框架,用来帮助你更轻松的创建web应用。这些框架把相应的模块组织起来,使得构建应用的时候可以更快捷,也不用去关注一些细节(例如socket和协议),所以需要的都在框架里了。
一个WEB框架基本都会有如下功能:
- 接受用户的请求(socket)
- 根据不同请求路径来分发
- 动态
今天我来先通过socket来实现一个简单的web框架,可以通过浏览器来访问,也可以根据请求路径的不同来分发请求。
01. socket实现一个服务端
# 这个socket服务端启动之后,就可以循环接受用户的请求 # 浏览器访问http://127.0.0.1:8000之后会在浏览器展示OK import socket sk = socket.socket() sk.bind(('127.0.0.1', 8000)) sk.listen(5) while True: conn, addr = sk.accept() ret = conn.recv(1024) print(ret) conn.send(b'HTTP/1.1 200 ok\r\ncontent-type: text/html\r\n\r\n') conn.send(b'OK') conn.close()
02. 根据不同的路径来分发请求
import socket sk = socket.socket() sk.bind(('127.0.0.1', 8000)) sk.listen(5) while True: conn, addr = sk.accept() ret = conn.recv(1024) url = ret.decode('utf-8').split()[1] print(ret) conn.send(b'HTTP/1.1 200 ok\r\ncontent-type: text/html; charset=utf-8\r\n\r\n') if url == '/index': data = '<h1>这是首页</h1>'.encode('utf-8') elif url == '/home': data = '<h1>HOME site</h1>'.encode('utf-8') else: data = b'<h1>400 client error</h1>' conn.send(data) conn.close()
03. 封装成函数
import socket sk = socket.socket() sk.bind(('127.0.0.1', 8000)) sk.listen(5) def index(url): return f'<h1>这是首页+{url}</h1>' def home(url): return f'<h1>这是home{url}</h1>' def api(url): return f'<h1>这是api{url}</h1>' while True: conn, addr = sk.accept() ret = conn.recv(1024) url = ret.decode('utf-8').split()[1] print(ret) conn.send(b'HTTP/1.1 200 ok\r\ncontent-type: text/html; charset=utf-8\r\n\r\n') if url == '/index': data = index(url) print(data) elif url == '/home': data = home(url) elif url == '/api': data = api(url) else: data = '<h1>400 client error</h1>' conn.send(data.encode('utf-8')) conn.close()
04.对上面的函数进行升级(可插拔),在不改变主代码的前提下增加功能(增加路径)
1 import socket 2 sk = socket.socket() 3 sk.bind(('127.0.0.1', 8000)) 4 sk.listen(5) 5 6 def index(url): 7 return f'<h1>这是首页+{url}</h1>' 8 9 def home(url): 10 return f'<h1>这是home{url}</h1>' 11 12 def api(url): 13 return f'<h1>这是api{url}</h1>' 14 15 def test(url): 16 return f'<h1>这是api{url}</h1>' 17 18 lst = [ 19 ('/index', index), 20 ('/home', home), 21 ('api', api), 22 ('/test', test) 23 ] 24 25 while True: 26 conn, addr = sk.accept() 27 ret = conn.recv(1024) 28 url = ret.decode('utf-8').split()[1] 29 # print(ret) 30 31 conn.send(b'HTTP/1.1 200 ok\r\ncontent-type: text/html; charset=utf-8\r\n\r\n') 32 func = None 33 for i in lst: 34 if i[0] == url: 35 # data = i[1](url) 36 # func = getattr(i, i[0], None) 37 func = i[1] 38 print(func) 39 break 40 41 if func: 42 data = func(url) 43 else: 44 data = '<h1>400 client error</h1>' 45 46 conn.send(data.encode('utf-8')) 47 48 conn.close()
改成上面的写法之后,以后有新路径需要增加时,我们不需要改变while True下面的内容了,只需要增加一个对应的函数,
然后把路径和函数的对应关系放到lst列表中就好了,这样写扩展性比较强;
05.动态返回html内容
import time import socket sk = socket.socket() sk.bind(('127.0.0.1', 8000)) sk.listen(5) def index(url): return f'<h1>这是首页+{url}</h1>' def home(url): with open('index.html', mode='r', encoding='utf-8') as f1: content = f1.read() print(content) return content def api(url): return f'<h1>这是api{url}</h1>' def test(url): return f'<h1>这是api{url}</h1>' #动态显示html内容,通过字符串替换的方式 def timer(url): with open('\timer.html', mode='r', encoding='utf-8') as f2: content = f2.read() # now_time = time.time() now1 = time.strftime('%Y-%m-%d %H:%M:%S') content = content.replace('#time#', now1) return content lst = [ ('/index', index), ('/home', home), ('api', api), ('/test', timer), ('/time', timer), ] while True: conn, addr = sk.accept() ret = conn.recv(1024) url = ret.decode('utf-8').split()[1] print(ret) conn.send(b'HTTP/1.1 200 ok\r\ncontent-type: text/html; charset=utf-8\r\n\r\n') func = None for i in lst: if i[0] == url: # data = i[1](url) # func = getattr(i, i[0], None) func = i[1] break if func: data = func(url) else: data = '<h1>400 client error</h1>' conn.send(data.encode('utf-8')) conn.close()
就这样一个简单的web框架就写完了,当然这只是做实验方便理解Django之类的框架。 Django框架上面这些都不用写,它们socket都已经被封装好了,还有很多功能都封装好了,我们只需要在Django里面写逻辑代码就行了;
w

浙公网安备 33010602011771号