“不畏惧,不讲究,将来的日子好好努力” ;你们好,我是小芝麻😄javascript
本文脑图较多,方便梳理,适合:前端小白php
今天小芝麻主要想阐述的就是一个问题:css
request请求阶段html
- 一、URL 地址解析
- 二、DNS 域名解析
- 三、和服务器创建 TCP 链接
- 四、发送 HTTP 请求
response 响应阶段前端
- 五、服务器获得并处理请求
断开链接java
- 六、和服务器断开 TCP 链接
渲染页面编程
- 七、客户端渲染服务器返回的内容
下面咱们会详细阐述以上几个方面具体都是啥;json
在开始正题以前,咱们先了解如下,这两个概念;后端
具体交互如图: 跨域
好的下面进入正题
前面的文章里写过关于 URL参数处理的问题,那到底什么是URL呢?
一个完整的URL所包含的内容
给服务器通网后,会有两个 IP 地址:
- 内网IP:局域网内访问
- 外网IP:外部用户基于外网IP访问到服务器(例如:125.39.174.200)
一级、二级、三级...域名都是由顶级域名衍生出来的,因此,公司在注册域名的时候,只要买下顶级域名就能够了,就例如 qq.com ,只须要买下 qq.com 就能够用 www.qq.com、sports.qq.com、kbs.sports.qq.com...等域名了。
若是项目采用的就是默认端口号,咱们在书写地址的时候,不用加端口号,浏览器在发送请求的时候会帮咱们默认给加上
默认的路径或者名称:xxx.com/stu/ 不指定资源名,服务器会找默认的资源,通常默认资源名是default.html、index.html... 固然这些能够在服务器端本身配置
注意伪URL地址的处理:
伪 URL 的目的:URL重写技术是为了增长SEO搜索引擎优化的,动态的网址通常不能被搜索引擎收录(因此咱们要把动态网址静态化,此时须要的是重写URL)
请求的地址中若是出现非有效 UNICODE 编码内容,现代版浏览器会默认的进行编码
编码方式:
客户端和服务器端进行信息传输的时候,若是须要把请求的地址和信息编码,咱们则基于以上两种方式处理, 服务器端也存在这些方法,这样就能够统一编码解码了
三、escape/unescape
例如:从列表跳转到详情,咱们能够把传递的中文信息基于这个编码,详情页获取编码后的信息再解码,再好比咱们在客户端种的cookie信息,若是信息是中文,咱们也基于这种办法编码...
而咱们发送请求时候所谓的DNS解析,其实就是根据域名,在DNS服务器上查找到对应服务器的外网IP
本地解析查找过程:
非本地解析:
DNS优化:
DNS缓存:通常浏览器会在第一次解析后,默认创建缓存,时间很短,只有一分钟左右
SYN:同步序列编号(Synchronize Sequence Numbers)
。以上是说的太过正式,下面说个白话版的👇:其实就相似于两我的打招呼的过程;
到此双方试探成功,创建友好的关系👬;(这条路算是打通了)
没有错,不要怀疑,就是这么简单~~
有了路以后,怎么传递数据呢,咱们还须要个快递小哥;(HTTP 就是快递小哥了)
HTTP 报文是由 请求报文+响应报文 共同组成
至于报文是啥?在哪查看咱们一会再说,先看下经常使用的状态码有哪些;
1~5开头,三位数字
=>谷歌浏览器F12
=>Network(全部客户端和服务器端的交互信息在这里均可以看到)
=>点击某一条信息,在右侧能够看到全部的HTTP报文信息
上图就是了😄,接下来咱们看几个经常使用的
主要分两种:
- GET 系列请求
- POST 系列请求
不论GET和POST均可以把信息传递给服务器,也能从服务器获取到结果
GET 与 POST 系列请求的区别(所谓的区别都是约定俗成的,并无必定要这样作的规定)
本质区别
GET系列传递给服务器信息的方式通常采用:问号传参
POST系列传递给服务器信息的方式通常采用:设置请求主体
本质区别所致使的问题
好了,HTTP请求就先说到这里😄
服务器接收到请求后:
上面咱们说 创建 TCP 链接,就是修路,HTTP 就是快递小哥,在小哥送完快递后,咱们就要把以前修好的路拆掉,就有了 TCP 四次挥手
白话文翻译👇:
为何创建链接协议是三次握手,而关闭链接倒是四次握手呢?
这篇咱们以前写过浏览器渲染页面的主体流程,此次咱们把主要的步骤在写一下。
渲染了全部的 HTML 标签
W3C
规范(第五代版本的规范H5)的规则,转换成咱们能看懂的标签DOM
节点DOM
节点之间的关系,生成DOM
树
请求回来 CSS 后,渲染完 CSS
同生成DOM
树同样的过程生成CSSOM
树
按照
RENDER-TREE
在设备的视口中进行结构和位置的相关计算=>布局(Layout)或 重排/回流(reflow)
根据渲染树以及回流获得的几何信息,获得节点的绝对像素=>绘制(painting)或 栅格化(rasterizing)
到此 “当用户在地址栏输入了网址,到看到页面中间都经历了什么?”这道题咱们算是解答完了。
做为前端咱们在写代码的时候,都是经过 AJAX 向服务器发送请求,下面咱们在说一下 AJAX 的基础知识和操做
全称:async javascript and xml(异步的 JS 和 XML)
此处的异步指的是:局部刷新(对应的是全局刷新)
全局刷新:服务器渲染
局部刷新:客户端渲染
XML:可扩展的标记语言,用本身自定义的标签来存储数据的
XML 格式
<?xml version="1.0" encoding="UTF-8"?>
<root>
<student>
<name>张三</name>
<age>25</age>
<score>
<english>95</english>
</score>
</student>
<student>
<name>张三</name>
<age>25</age>
</student>
<student>
<name>张三</name>
<age>25</age>
</student>
</root>
复制代码
JSON 格式
[{
"name": "张三",
"age": 25,
"score": {
"english": 95
}
}, {
"name": "张三",
"age": 25
}, {
"name": "张三",
"age": 25
}]
复制代码
AJAX任务:发送一个请求给服务器,从服务器获取到对应的内容是从SEND后开始到XHR.READYSTATE===4的时候算任务结束
核心四步
1.建立AJAX实例
2.打开URL(配置发送请求的信息)
3.监听AJAX状态
4.发送请求
//1.建立AJAX实例
let xhr=new XMLHttpRequest;
//2.打开URL(配置发送请求的信息)
xhr.open('GET','./json/xxx.json',true);
//3.监听AJAX状态,在状态为X的时候,获取服务器响应的内容
xhr.onreadystatechange=function(){
if(xhr.readyState===4 && /^(2|3)\d{2}$/.test(xhr.status)){
let result = xhr.responseText;
}
}
//4.发送请求
//SEND中放的是请求主体的内容
xhr.send(null);
//=> AJAX任务(发送一个请求给服务器,从服务器获取到对应的内容)
//=> 从SEND后开始,到XHR.READYSTATE===4的时候算任务结束
复制代码
客户端怎么把信息传递给服务器?
服务器怎么把信息返回给客户端?
/* * 倒计时抢购要注意的细节知识点: * 1.计算剩余多久须要的时间不能是客户端本机的时间,须要获取服务器的时间 * (基于AJAX请求向服务器获取,可是也不能每隔1秒都去请求一次 * 【咱们是第一次加载页面的时候,从服务器获取服务器时间,存储起来,后期咱们把 * 这个时间自动的每隔1秒进行累加,页面刷新还须要从服务器获取】) * 2.为了保证绝对安全,在购买的时候,服务器须要二次校验时间的合法性 * 3.下降服务器返回时间和真实时间的偏差(减小服务器的响应时间) * 1)请求方式基于HEAD,只获取响应头信息便可 * 2)在AJAX状态为2的时候处理,无需等到状态为4 */
复制代码
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0">
<title>Document</title>
<!-- IMPORT CSS -->
<style> * { margin: 0; padding: 0; } #box { box-sizing: border-box; padding: 20px; width: 200px; margin: 20px auto; background: lightblue; line-height: 50px; } </style>
</head>
<body>
<div id="box">
距离秒杀还差:
<span id="content">00:00:00</span>
</div>
<!-- IMPORT JS -->
<script src="1.js"></script>
</body>
</html>
复制代码
JS
let box = document.querySelector('#box'),
content = document.querySelector('#content'),
timer = null;
// 获取服务器时间
function getServerTime() {
return new Promise(resolve => {
let xhr = new XMLHttpRequest;
xhr.open('head', './data.json?_=' + Math.random());
xhr.onreadystatechange = () => {
if (xhr.readyState === 2 && /^(2|3)\d{2}$/.test(xhr.status)) {
let time = xhr.getResponseHeader('date');
// 获取的TIME是格林尼治时间 GMT(北京时间 GMT+0800)
time = new Date(time);
resolve(time);
}
};
xhr.send(null);
});
}
// 根据服务器时间计算倒计时
function computed(time) {
// time从服务器获取的当时间
// target是抢购的目标时间
// spanTime两个时间的毫秒差
let target = new Date('2020/05/13 15:57:35'),
spanTime = target - time;
if (spanTime <= 0) {
// 已经到达抢购的时间节点了
box.innerHTML = "开始抢购吧!";
clearInterval(timer);
return;
}
// 计算出毫秒差中包含多少小时、多少分钟、多少秒
let hours = Math.floor(spanTime / (60 * 60 * 1000));
spanTime = spanTime - hours * 60 * 60 * 1000;
let minutes = Math.floor(spanTime / (60 * 1000));
spanTime = spanTime - minutes * 60 * 1000;
let seconds = Math.floor(spanTime / 1000);
hours < 10 ? hours = '0' + hours : null;
minutes < 10 ? minutes = '0' + minutes : null;
seconds < 10 ? seconds = '0' + seconds : null;
content.innerHTML = `${hours}:${minutes}:${seconds}`;
}
getServerTime().then(time => {
// 获取到服务器时间后,计算倒计时
computed(time);
// 每间隔1秒中,让获取的时间累加1秒,在从新计算倒计时结果
timer = setInterval(() => {
time = new Date(time.getTime() + 1000);
computed(time);
}, 1000);
});
复制代码
今天的文章到此结束,小芝麻自知还有不少不足,提高空间还有很大很大,感谢打什么批评指正🙏