一、Djiango介绍
二、http协议介绍
三、网络的七层协议 http协议本质是基于socket实现
四、web服务器的实现
五、总结
Django是一个用 Python 编写的 Web 框架。Web 框架是一种软件,基于web框架可以开发动态网站,各种应用程序以及服务。它提供了一系列工具和功能,可以解决许多与Web开发相关的常见问题,比如:安全功能,数据库访问,会话,模板处理,URL路由,国际化,本地化,等等
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。
简单快速:客户向服务器请求服务时,只需传送请求方法和路径。
灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记
无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。[与网络层tcp三次握手对应记忆]
无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
支持B/S和C/S模式
HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。以下面这个URL为例,介绍下普通URL的各部分组成:
http://www.aspxfans.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name
从上面的URL可以看出,一个完整的URL包括以下几部分:
1.协议部分:该URL的协议部分为“http:”,这代表网页使用的是HTTP协议。在Internet中可以使用多种协议,如HTTP,FTP等等本例中使用的是HTTP协议。在"HTTP"后面的“//”为分隔符
2.域名部分:该URL的域名部分为“www.aspxfans.com”。一个URL中,也可以使用IP地址作为域名使用
3.端口部分:跟在域名后面的是端口,域名和端口之间使用“:”作为分隔符。端口不是一个URL必须的部分,如果省略端口部分,将采用默认端口
4.虚拟目录部分:从域名后的第一个“/”开始到最后一个“/”为止,是虚拟目录部分。虚拟目录也不是一个URL必须的部分。本例中的虚拟目录是“/news/”
5.文件名部分:从域名后的最后一个“/”开始到“?”为止,是文件名部分,如果没有“?”,则是从域名后的最后一个“/”开始到“#”为止,是文件部分,如果没有“?”和“#”,那么从域名后的最后一个“/”开始到结束,都是文件名部分。本例中的文件名是“index.asp”。文件名部分也不是一个URL必须的部分,如果省略该部分,则使用默认的文件名
6.锚部分:从“#”开始到最后,都是锚部分。本例中的锚部分是“name”。锚部分也不是一个URL必须的部分
7.参数部分:从“?”开始到“#”为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为“boardID=5&ID=24618&page=1”。参数可以允许有多个参数,参数与参数之间用“&”作为分隔符
(http协议详情见原文:https://www.cnblogs.com/ranyonsue/p/5984001.html)
HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)
应用层–>表示层–>会话层–>传输层–>网络层–>物理层
http 协议 tcp/udp socket编程
概念
http:浏览器发送请求,服务器进行响应;
socket编程,即客户端和服务器通信;二者原理一致。Http协议可以说是基于Socket的再上层封装。
0、基于socket编程实现web服务器
import socket
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 8080))
status = 1
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, status)
sock.listen(5)
while True:
# 等待浏览器的访问
conn,addr = sock.accept()
# 接收浏览器发来的请求内容[recv]
data = conn.recv(1024)
print(data)
# 给浏览器返回内容[send]
conn.send(b"HTTP/1.1 200 OK\r\nContent-Type:text/html; charset=utf-8\r\n\r\n")
#注意编码
conn.send("how are you? aa".encode('utf-8'))
# 关闭socket
conn.close()
if __name__ == '__main__':
main()
如果是要返回一个图片呢?一个文件呢?【app】这就涉及你自己要负责实现文件的传送了,我们学socket传文件时,遇到过粘包问题,解决起来挺麻烦的,利用现成的东西wsgi
WSGI(Web Server Gateway Interface)是一种规范。建立这种规范,程序就不再重复编写web server(socket服务端),而是直接使用现成的实现WSGI的模块(例如:wsgiref、uwsgi、werkzeug),从而让程序员更加专注与业务代码。
1、利用wsgiref 实现一个web服务器
# 基于wsgiref实现web服务器
from wsgiref.simple_server import make_server
def run_server(environ, start_response):
"""
当用户访问http://127.0.0.1:8000/ 立即执行该函数并将函数的返回值返回给用户浏览器
:param environ: 请求相关的内容,比如浏览器类型、版本、来源地址、url 等同于socket编程中收到的浏览器信息
:param start_response:响应相关的内容
:return:
"""
start_response('200 OK', [('Content-Type', 'text/html')])
return [bytes("hahahaha",encoding='utf-8')]
if __name__ == '__main__':
httpd = make_server('localhost', 8000, run_server)
httpd.serve_forever()
2、利用wsgiref 实现支持多url的web服务器 [路由系统,输入不同的url查看不同的内容]
#基于wsgiref实现多路由的web服务器
#实现路由分发器,将url与对应的函数进行匹配
from wsgiref.simple_server import make_server
def book(environ, start_response):
print("book page")
return [bytes(' book page
',encoding='utf-8')]
def cloth(environ, start_response):
print('cloth page')
return [bytes(' cloth page
', encoding='utf-8')]
def routers():
urls_info = {
'/book': book,
'/cloth': cloth,
}
return urls_info
def run_server(environ, start_response):
"""
:param environ: 浏览器请求的相关信息 版本、url
:param start_response: 响应信息
:return:
"""
start_response('200 OK', [('Content-Type', 'text/html')])
url = environ.get('PATH_INFO')
# print("url:",url)
urlpatterns = routers()
if url in urlpatterns:
# 接收函数返回的值
func_data=urlpatterns[url](environ, start_response)
# 将接收的值返回给浏览器
return func_data
else:
return [bytes('not find
',encoding='utf-8')]
if __name__ == '__main__':
httpd = make_server('localhost', 8000, run_server)
httpd.serve_forever()
3、利用wsgiref 实现图片显示的服务器
图片显示的原理:每一张图片为单独的一次请求。[没有加载出来]
# 基于wsgiref 实现图片显示服务器
import os
import re
BASE_DIR = os.path.abspath(__file__) #当前文件绝对路径
BASE_PATH = os.path.dirname(BASE_DIR) # 前面的路径
from wsgiref.simple_server import make_server
def book(environ, start_response):
print("book page")
start_response('200 OK', [('Content-Type', 'text/html')])
# 前端路径
data = """
欢迎来到日本专区
上路飞学城,看尽天下大片
"""
return [bytes(data, encoding='utf-8')]
#return [bytes(' book page
',encoding='utf-8')]
def cloth(environ, start_response):
print('cloth page')
start_response('200 OK', [('Content-Type', 'text/html')])
return [bytes(' cloth page
', encoding='utf-8')]
def routers():
urls_info = {
'/book': book,
'/cloth': cloth,
}
return urls_info
def img_handler(url):
"""
:param url: 前端访问的url /data/imgs/book.jpg
:return: 找到后台数据的位置(re.sub),然后打开文件,将数据返回给前端
打开文件时,先判断文件是否存在
"""
# print("BASE_DIR:", BASE_DIR)
print("BASE_PATH:", BASE_PATH)
img_path =re.sub('/static', '/static_data', url)
# img_path = os.path.join(BASE_DIR,img_path)
img_abs_path = "%s%s" % (BASE_PATH, img_path)
#print('img_abs_path:', img_abs_path)
if os.path.isfile(img_abs_path):
#print("------file exist-------")
f = open("img_abs_path ", "rb")
data = f.read() #获取图片内容
return [data, 0] # 0 表示没有错 1 有错
else:
return [None, 1]
def run_server(environ, start_response):
"""
:param environ: 浏览器请求的相关信息 版本、url
:param start_response: 响应信息
:return:
"""
url = environ.get('PATH_INFO')
print("url:",url)
urlpatterns = routers()
if url in urlpatterns:
func_data=urlpatterns[url](environ, start_response)
return func_data
elif url.startswith('/static/'):# 代表图片
img_data, img_status = img_handler(url)
if img_status == 0:
start_response("200 OK", ["Content-Type", 'text/jpeg'])
return [img_data, ]
else:
start_response("404", ['Content-Type', 'text/html'])
return [bytes('404,not find',encoding='utf-8')]
if __name__ == '__main__':
httpd = make_server('localhost', 8000, run_server)
httpd.serve_forever()
1、浏览器是socket客户端,网站是socket服务器
2、wsgi是一个规范,wsgiref 实现了这个规范 并且 在其内部实现了socket服务端
3、根据不同的url去执行不同的函数,即为路由系统
4、函数 即处理业务逻辑
5、图片、css、js文件统一称为静态文件。需要经过 从前端获取url---->找到后端的位置----->打开文件---->读取文件---->返回给浏览器