Django 底层原理HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP是万维网WEB的数据通信的基础。HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。
HTTP协议采用了请求/响应模型。
客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。
响应报文:比如"HTTP/1.1 200 OK"

以下是 HTTP 请求/响应的步骤:
客户端连接到Web服务器
一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。例如,http://www.luffycity.com。
发送HTTP请求
通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。
服务器接受请求并返回HTTP响应
Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
释放连接TCP连接
若connection 模式为 close(无连接),则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若 connection 模式为 keepalive(短连接),则该连接会保持一段时间,在该时间内可以继续接收请求;
客户端浏览器解析HTML内容
客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
例如:在浏览器地址栏键入URL,按下回车之后会经历以下流程:
基于 请求-响应 的模式
无状态保存
概念:
目的:
弊端:
信息的不存储,对于必须要存储某些信息的网站来说,意味着:
我输入一个网页并回车,一个套接字返回我要访问的html,然后他就走了,然后当我要进行登陆操作时,又来了一个套接字接待我,给我返回登陆的网页,然后他也走了。我在输入完信息后回车进行登陆,又一个套接字过来拿着我的请求中的信息去数据库里进行比对,检验完后,它就走了,临走前返回我一个登陆成功,这时,如果我要进行基于用户的操作时,一个新的套接字过来说,你还没登陆啊,怎么能进行这个操作,我....基于上述情况,cookie由此诞生。
无连接
短连接:
概念:
目的
短连接等待时间
优势:
因此,无连接、短连接没有绝对的优劣,主要还是看客户端需求。


超文本传输协议(HTTP)的统一资源定位符将从因特网获取信息的五个基本元素包括在一个简单的地址中(即一个完整的网页):
以http://www.luffycity.com:80/news/index.html?id=250&page=1 为例, 其中:http,是协议;www.luffycity.com,是服务器;80,是服务器上的默认网络端口号,默认不显示;/news/index.html,是路径(URI:直接定位到对应的资源);?id=250&page=1,是查询。大多数网页浏览器不要求用户输入网页中“http://”的部分,因为绝大多数网页内容是超文本传输协议文件。同样,“80”是超文本传输协议文件的常用端口号,因此一般也不必写明。一般来说用户只要键入统一资源定位符的一部分(www.luffycity.com:80/news/index.html?id=250&page=1)就可以了。由于超文本传输协议允许服务器将浏览器重定向到另一个网页地址,因此许多服务器允许用户省略网页地址中的部分,比如 www。从技术上来说这样省略后的网页地址实际上是一个不同的网页地址,浏览器本身无法决定这个新地址是否通,服务器必须完成重定向的任务。

from threading import Threadimport socketserver = socket.socket()server.bind(('127.0.0.1',8001))server.listen()def html(): with open('home.html', 'rb') as f: to_client_data = f.read() return to_client_datadef css(): with open('home.css', 'rb') as f: to_client_data = f.read() return to_client_datadef js(): with open('home.js', 'rb') as f: to_client_data = f.read() return to_client_datadef jpg(): with open('1.jpg', 'rb') as f: to_client_data = f.read() return to_client_datadef ico(): with open('xx1.ico', 'rb') as f: to_client_data = f.read() return to_client_dataurl_patterns = [ ('/',html), ('/home.css',css), ('/home.js',js), ('/1.jpg',jpg), ('/favicon.ico',ico),]while 1: conn,addr = server.accept() from_client_msg = conn.recv(1024).decode('utf-8') # print(from_client_msg) # print(from_client_msg.decode('utf-8')) request_path = from_client_msg.split(' ')[1] # 拿到用户的访问路径 print(request_path) conn.send(b'HTTP/1.1 200 ok\r\n\r\n') for i in url_patterns: if i[0] == request_path: # 进行信息比对,你要访问的路径在我的url-func关系中,就调用对应的函数给他返回对应页面。 to_client_data = i[1]() conn.send(to_client_data) conn.close()server.close()from threading import Threadimport socketserver = socket.socket()server.bind(('127.0.0.1',8001))server.listen()def html(conn): with open('home.html', 'rb') as f: to_client_data = f.read() conn.send(to_client_data) conn.close() # return to_client_datadef css(conn): with open('home.css', 'rb') as f: to_client_data = f.read() conn.send(to_client_data) conn.close()def js(conn): with open('home.js', 'rb') as f: to_client_data = f.read() conn.send(to_client_data) conn.close()def jpg(conn): with open('1.jpg', 'rb') as f: to_client_data = f.read() conn.send(to_client_data) conn.close()def ico(conn): with open('xx1.ico', 'rb') as f: to_client_data = f.read() conn.send(to_client_data) conn.close()url_patterns = [ ('/',html), ('/home.css',css), ('/home.js',js), ('/1.jpg',jpg), ('/favicon.ico',ico),]while 1: conn,addr = server.accept() from_client_msg = conn.recv(1024).decode('utf-8') request_path = from_client_msg.split(' ')[1] print(request_path) conn.send(b'HTTP/1.1 200 ok\r\n\r\n') for i in url_patterns: if i[0] == request_path: target_thread = Thread(target=i[1],args=(conn,)) # to_client_data = i[1]() target_thread.start() server.close() # 注意:这里不能跟函数web框架一样在循环外关闭套接字、服务器 # 因为我的代码里只有一个变量名。通俗点形容:当一个客户来访问服务器,我就创建一个线程给他个名字叫:conn,并让她去服务这个客户,他俩离开后,如果又来一个用户,我就再创建一个线程,并且把之前那个线程的名字给拿走给这个新的线程,但是这样并不影响之前的线程服务用户,他俩玩他俩的。 # 但当其中一个线程先运行完后,他就会执行循环外的conn.close(),这时如果正好创建了一个线程,把名字也给了,但是还没来得及去服务,他就被辞职了,这时没人服务用户了,程序就出错了!而且,在辞职完conn后,还要关门停止营业,这就不是我预期的效果了。动态页面的意思是:同一个url,我每次打开时都不同于之前。而非,带闪图、动态等重复变化的页面。
from threading import Threadimport socketimport timeserver = socket.socket()server.bind(('127.0.0.1',8001))server.listen()def html(conn): current_time = time.time() # import pymysql with open('home.html', 'r',encoding='utf-8') as f: to_client_data = f.read() to_client_data = to_client_data.replace('%xxoo%',str(current_time)) conn.send(to_client_data.encode('utf-8')) conn.close() # return to_client_datadef css(conn): with open('home.css', 'rb') as f: to_client_data = f.read() conn.send(to_client_data) conn.close()def js(conn): with open('home.js', 'rb') as f: to_client_data = f.read() conn.send(to_client_data) conn.close()def jpg(conn): with open('1.jpg', 'rb') as f: to_client_data = f.read() conn.send(to_client_data) conn.close()def ico(conn): with open('xx1.ico', 'rb') as f: to_client_data = f.read() conn.send(to_client_data) conn.close()url_patterns = [ ('/',html), ('/home.css',css), ('/home.js',js), ('/1.jpg',jpg), ('/favicon.ico',ico),]while 1: conn,addr = server.accept() from_client_msg = conn.recv(1024).decode('utf-8') request_path = from_client_msg.split(' ')[1] print(request_path) conn.send(b'HTTP/1.1 200 ok\r\n\r\n') for i in url_patterns: if i[0] == request_path: target_thread = Thread(target=i[1],args=(conn,)) # to_client_data = i[1]() target_thread.start()server.close()wsgiref模块是对socket的封装,其内部的environ是对http信息进行了切割,并整理成一个字典,想要用户的什么数据,只要知道这个数据对应的键名就可以直接拿到了,而什么数据对应什么键都是其内部定义好了的,所以用起来很方便。
Django中也有可以实现wsgiref模块功能的元素,也是通过某些功能直接将http信息做好了切割,保存,通过指定方式去拿指定信息就可以了。
from wsgiref.simple_server import make_serverurl_patterns = [('/index',index),]def index(): with open('html', 'rb') as f: to_client_data = f.read() return to_client_datadef application(environ, start_response): """ :param environ: 封装了所有的http协议相关信息--一个字典{'path_info':'/'} :param start_response: :return: """ request_path = environ['PATH_INFO'] # 通过固定键名'PATH_INFO'直接拿到用户的请求路径 for i in url_patterns: if i[0] == request_path: ret = i[1]() start_response('200 OK', [('k1','v1'),]) # print(environ) # print(environ['PATH_INFO']) return [ret]httpd = make_server('127.0.0.1', 8080, application)httpd.serve_forever()
SQL 语句实现的。第三层是数据库服务器,他扮演着重要的角色,因为它存放着大量的数据。当数据库服务器收到了WEB服务器的请求后,会对 SQL 语句进行处理,并将返回的结果发送给WEB服务器,接下来,WEB服务器将收到的数据结果转换为HTML文本形式发送给浏览器,也就是我们打开浏览器看到的界面。

在 B/S 模式中,用户是通过浏览器针对许多分布于网络上的服务器进行请求访问的,浏览器的请求通过服务器进行处理,并将处理结果以及相应的信息返回给浏览器,其他的数据加工、请求全部都是由Web Server完成的。通过该框架结构以及植入于操作系统内部的浏览器,该结构已经成为了当今软件应用的主流结构模式。
www 条件下,B/S明显胜过C/S。可以这么说,B/S的强项就是C/S的弱项,反之亦然。它们各有优缺点,相互无法取代。C/S与B/S不同点
| C/S | B/S | |
|---|---|---|
| 硬件环境 | 专用网络 | 广域网 |
| 安全要求 | 面向相对固定的用户群信息安全的控制能力强 | 面向不可知的用户群对安全的控制能力相对较弱 |
| 程序架构 | 更加注重流程系统运行速度可较少考虑 | 对安全以及访问速度都要多重的考虑,是发展趋势 |
| 软件重用 | 差 | 好 |
| 系统维护 | 升级难 | 开销小,方便升级 |
| 处理问题 | 集中 | 分散 |
| 用户接口 | 与操作系统关系密切 | 跨平台,与浏览器相关 |
| 信息流 | 交互性低 | 交互密集 |