前端知识体系8.前后端通讯
本文目录:
- 1.HTTPS和HTTP的区别
- 2.http1.0、1.1、2.0、3.0的区别?
- 3.你了解哪些请求方法,分别有哪些作用和不同
- 4.什么是CA证书?整个网站进行验证的流程是什么?
- 5.SOCKET?UDP?DNS?FTP?以及不常用的其他协议?
- 6.HTTP协议常见的状态码
- 7.说一下AJAX和AXIOS的区别
- 8.URL从输入到输出的过程
- 9.前后端联调之Form Data与Request Payload
- 10.post请求的form-data和x-www-form-urlencoded和raw和binary了解多少,在使用axios发请求的时候怎么对这些进行处理
- 11.说下HTTP常见的请求头和响应头
- 12.怎么与服务端保持连接
- 13.http请求跨域问题及解决方法,JSONP和ajax有什么区别
- 14.说下HTTP的报文结构
- 15.说说Get和Post的区别
- 16.什么是无状态协议,HTTP 是无状态协议吗,怎么解决(JWT)
- 17.说说你了解的HTTP 的缓存策略
- 18.在你开发的过程中,什么情况下会遇到跨域问题,你是怎么解决的?
- 19.什么是HTTP链接的管线化
- 20.前后端通讯的主要方式
- 21.前端请求的常用触发方式
- 22.为什么TCP建立连接不能是两次握手?
- 23.为什么TCP断开连接挥手需要四次?
1.HTTPS和HTTP的区别
HTTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
2.http1.0、1.1、2.0、3.0的区别?
http 1.0
短连接,每个资源文件都需要一次tcp三次握手和四次挥手,耗费网络资源
线头阻塞,请求队列的第一个请求因为服务器正忙(或请求格式问题等其他原因),导致后面的请求被阻塞。
http 1.1
长连接,keep-alive,一次流程即可
使用多个TCP链接,客户端可以并行发送最多 N个请求,服务器可以并行处理最多 N个请求
增了许多动词方法:PUT、PATCH、HEAD、 OPTIONS、DELETE
扩充了请求头和响应头的一些功能,比如请求头信息新增了Host字段,用来指定服务器的域名
http 2.0
长连接+IO多路复用模型
Header压缩,在HTTP1.0中,我们使用文本的形式传输header,在header中携带cookie的话,每次都需要重复传输几百到几千的字节,这着实是一笔不小的开销。在HTTP2.0中,我们使用了HPACK(HTTP2头部压缩算法)压缩格式对传输的header进行编码,减少了header的大小。并在两端维护了索引表,用于记录出现过的header,后面在传输过程中就可以传输已经记录过的header的键名,对端收到数据后就可以通过键名找到对应的值。
http 3.0
谷歌开发的QUIC协议,利用UDP实现可靠数据传输。
3.你了解哪些请求方法,分别有哪些作用和不同
HTTP 协议中共定义了八种方法或者叫“动作”来表明对 Request-URI 指定的资源的不同操作方式,具体介绍如下:
OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送'*'的请求来测试服务器的功能性。
HEAD:向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。
GET:向特定的资源发出请求。
POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改。
PUT:向指定资源位置上传其最新内容。
DELETE:请求服务器删除 Request-URI 所标识的资源。
TRACE:回显服务器收到的请求,主要用于测试或诊断。
CONNECT:HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
虽然 HTTP 的请求方式有 8 种,但是我们在实际应用中常用的也就是 get 和 post,其他请求方式也都可以通过这两种方式间接的来实现。
4.什么是CA证书?整个网站进行验证的流程是什么?
CA证书就是电子商务认证授权机构,也称为电子商务认证中心,是负责发放和复管理数字证书的权威机构,并作为电子商务交易中受信任的第三方,承担公钥体系中公钥的合法性检验的责任制。
HTTPS的整体过程分为证书验证和数据传输阶段,具体的交互过程如下:
① 证书验证阶段
1.浏览器发起 HTTPS 请求
2.服务端返回 HTTPS 证书
3.客户端验证证书是否合法,如果不合法则提示告警
② 数据传输阶段
1.当证书验证合法后,在本地生成随机数
2.通过公钥加密随机数,并把加密后的随机数传输到服务端
3.服务端通过私钥对随机数进行解密
4.服务端通过客户端传入的随机数构造对称加密算法,对返回结果内容进行加密后传输
5.SOCKET?UDP?DNS?FTP?以及不常用的其他协议?
SOCKET
套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
SOCKET连接与TCP连接
Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。
创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。
HTTP和TCP
TCP是底层通讯协议,定义的是数据传输和连接方式的规范
HTTP是应用层协议,定义的是传输数据的内容的规范
HTTP协议中的数据是利用TCP协议传输的,所以支持HTTP也就一定支持TCP
TCP/IP协议
TCP/IP协议是一个协议簇。里面包括很多协议的,UDP只是其中的一个, 之所以命名为TCP/IP协议,因为TCP、IP协议是两个很重要的协议,就用他俩命名了。
TCP和UDP
都属于是网络数据的传输协议,UDP建立连接需要三次握手,断开连接需要四次挥手,安全可靠性更强,但是传输效率相对UDP低,UDP发送数据之前不需要建立连接。TCP连接只能是点到点、一对一的,而UDP支持一对一,一对多,多对一和多对多的交互通信,对实时性要求高的情景如视频通话等适用于UDP协议。
DNS
域名系统(服务)协议(DNS)是一种分布式网络目录服务,主要用于域名与 IP 地址的相互转换,以及控制因特网的电子邮件的发送。
由根DNS服务器、顶级域 DNS 服务器和权威 DNS 服务器组成。
解析顺序是首先从浏览器缓存、操作系统缓存以及本地 DNS 缓存 (/etc/hosts) 逐级查找,然后从本地 DNS 服务器、根 DNS、顶级 DNS 以及权威 DNS层层递归查询。
还可以基于域名在内网、外网进行负载均衡。
FTP
FTP(文件道传输) FTP就是文件传输协议,通过FTP,用户可以从Internet网上的一台内机器向另一台机器复制文件,可以用这种方式获取大量的文档,数据和其他的信息。
6.HTTP协议常见的状态码
1xx: 表示目前是协议处理的中间状态,还需要后续操作。
2xx: 表示成功状态。
3xx: 重定向状态,资源位置发生变动,需要重新请求。
4xx: 请求报文有误。
5xx: 服务器端发生错误。
具体常见的一些状态码
200-请求成功
301-永久重定向
302和307-临时重定向
304-客户端有缓存的文档并发出了一个条件性的请求,服务器告诉客户端,原来缓存的文档还可以继续使用
400-当前请求不能被服务器理解或请求参数有误
401-请求需要认证或认证失败
403-服务器禁止访问
404-资源未找到
405-方法未允许
500-内部服务器错误
502-网关错误
503-服务器处于超负载或停机维护
7.说一下AJAX和AXIOS的区别
AJAX
AJAX最初作用就是在不重新加载整个页面的情况下与服务器交换数据并更新部分网页。
本身是为了针对MVC编程而诞生的。
AJAX是异步的JavaScript 和 XML(标准通用标记语言的子集)。
AXIOS
AXIOS是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范。
8.URL从输入到输出的过程
- 构建请求
构建请求行,请求行包括请求方法、请求http版本等
- 构建请求
- 查找强缓存
检查强缓存,命中则直接使用,否则检查协商缓存
- 查找强缓存
- DNS解析
浏览器首先会查看本地硬盘的hosts文件,看看有没有域名对应的规则,如果有的话直接使用hosts文件里对应的ip地址,如果没有则会发出DNS请求域名与IP地址映射
- DNS解析
- 4.建立tcp连接
chrome限制同一域名下最多6个tcp连接
通过三次握手建立连接
三次握手过程:
1.客户端向服务器发送连接请求,传递一个数据包syn,此时客户端处于SYN_SEND状态
2.服务器接收syn报文后,会以自己的syn报文作为应答,传递数据包syn+ack,此时服务器处于SYN-REVD状态
3.客户端接收syn报文后,发送一个数据包ack,此时客户端处于ESTABLISHED状态,双方已建立连接
进行数据传输
通过四次挥手断开连接
四次挥手过程:
- 客户端发送一个FIN报文,报文中指定一个序列号,此时客户端处于FIN_WAIT1状态,等待服务器确认
- 服务器接收到FIN后,会发送ACK确认报文,表明已经收到客户端报文,此时服务端处于CLOSE_WAIT2状态
- 服务器发送FIN,告诉客户端想断开连接,此时服务端处于LAST_CHECK阶段
- 客户端收到FIN后,一样发送一个ACK作为应答,此时客户端处于TIME_WAIT阶段。需要过一段时间确认服务端收到自己的ACK报文
后才会进入CLOSED状态
5.发送http请求
6.网络响应
7.浏览器解析和渲染
分为构建dom树、样式计算、生成布局树。
8.生成布局
触发回流和重绘
9.前后端联调之Form Data与Request Payload
Request Payload更准确的说是http request的payload body。一般用在数据通过POST请求或者PUT请求。它是HTTP请求中空行的后面那部分。(PS:这里涉及一个http常被问到的问题,http请求由哪几部分组成,一般是请求行,请求头,空行,请求体。payload body应该是对应请求体。)
如果你正常请求一个ajax。浏览器会简单的将你提交的内容作为payload展示出来,这就是它所能做的,因为它不知道数据来自哪里。
如果你提交了一个html表单并且配置上了method="post",并且设置了Content-Type: application/x-www-form-urlencoded或者Content-Type: multipart/form-data。那么你的请求可能长这个样:
POST /some-path HTTP/1.1
Content-Type: application/x-www-form-urlencoded
foo=bar&name=John
这里的form-data就是request payload。在这里,浏览器知道更多:它知道bar是提交表单的输入字段foo的值。这就是它向你展示的。
所以区别就是,他们只是因为Content-Type设置的不同,并不是数据提交方式的不同,这两种提交都会将数据放在message-body中。但是chrome浏览器的开发者工具会根据这个ContentType区分显示方式。
Content-Type的差异
1.传统的ajax请求时候,Content-Type默认为"文本"类型。
2.传统的form提交的时候,Content-Type默认为"Form"类型。
3.axios传递字符串的时候,Content-Type默认为"Form"类型。
4.axios传递对象的时候,Content-Type默认为"JSON"类型
无论何种形式传递,后端解析表单信息的时候,会考虑Content-Type。如果是JSON字符串的话,后端解析payload的内容时候,肯定要去解析JSON啦。如果是key1=value1&key2=value2的形式,则需要去分割字符串。
当然这些事情一般后端使用的框架会去处理,但是框架给后端提供取值接口有可能是不同的,所以前端的小伙伴在处理请求问题时,一定要跟后端小伙伴商量好,是用JSON还是FormData。
10.post请求的form-data和x-www-form-urlencoded和raw和binary了解多少,在使用axios发请求的时候怎么对这些进行处理
**1.multipart/form-data **
使用表单上传文件时,必须让 form 的 enctyped 等于这个值。
multipart/form-data既可以上传文件,也可以上传键值对,它采用了键值对的方式,所以可以上传多个文件。
2.x-www-form-urlencoded:
浏览器的原生form 表单,如果不设置enctype属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。请求类似于下面这样
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。jQuery的Ajax的默认Content-Type就是这种。
3.raw
可以上传任意格式的文本,可以上传text、json、xml、html等
4.binary
相当于Content-Type:application/octet-stream,从字面意思得知,只可以上传二进制数据,通常用来上传文件,由于没有键值,所以,一次只能上传一个文件。
5.application/json
JSON格式支持比键值对复杂得多的结构化数据,所以application/json是比application/x-www-form-urlencoded更适合复杂交互的替代品,Axios的Content-Type默认就是application/json
6.text/xml
text/xml传输的是XML结构的数据,语言显得有些臃肿,虽用途也很广泛,但我们在实际项目中还是用json更加灵活方便。
POST http://www.example.com HTTP/1.1
Content-Type: text/xml
<?xml version="1.0"?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>41</i4></value>
</param>
</params>
</methodCall>
修改axios请求的头部
首先需要明确一点,当使用axios发送对象数据的时候,axios默认的请求头content-type类型。如果前后端的content-type设置不一样,会导致请求数据获取不到。明明自己的请求地址和参数都对了却得不到数据。
axios修改content-type可以选择引用axios自带的qs
import axios from 'axios'
import qs from 'querystring'
//如果想传过去的参数是字符串就是这用形式
axios.post(url, qs.stringify(params), {
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
}).then(res => res.data)
//如果想传过去的参数是对象就是这用形式
axios.post(url, qs.parse(qs.stringify(params)), {
headers: {
'Content-Type': 'application/json;charset=UTF-8'
}
11.说下HTTP常见的请求头和响应头
HTTP 标头会分为四种,分别是 通用标头、实体标头、请求标头、响应标头。分别介绍一下:
通用标头
Date
Date 是一个通用标头,它可以出现在请求标头和响应标头中,它的基本表示如下
Date: Wed, 21 Oct 2015 07:28:00 GMT
表示的是格林威治标准时间,这个时间要比北京时间慢八个小时
Cache-Control
Cache-Control 是一个通用标头,他可以出现在请求标头和响应标头中,Cache-Control 的种类比较多,虽然说这是一个通用标头,但是有一些特性是请求标头具有的,有一些是响应标头才有的。主要大类有 可缓存性、阈值性、 重新验证并重新加载 和其他特性
Connection
Connection 决定当前事务(一次三次握手和四次挥手)完成后,是否会关闭网络连接。Connection 有两种,一种是持久性连接,即一次事务完成后不关闭网络连接
Connection: keep-alive
另一种是非持久性连接,即一次事务完成后关闭网络连接
Connection: close
Cache-Control
控制缓存的行为
实体标头
实体标头是描述消息正文内容的 HTTP 标头。实体标头用于 HTTP 请求和响应中。头部Content-Length、 Content-Language、 Content-Encoding、 Content-Type是实体头。
Content-Type:实体主体的媒体类型
请求标头
Host:
Host 请求头指明了服务器的域名(对于虚拟主机来说),以及(可选的)服务器监听的 TCP 端口号。如果没有给定端口号,会自动使用被请求服务的默认端口(比如请求一个 HTTP 的 URL 会自动使用 80 作为端口)。
Referer:
HTTP Referer 属性是请求标头的一部分,当浏览器向 web 服务器发送请求的时候,一般会带上 Referer,告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理。
Referer: https://developer.mozilla.org/testpage.html
Accept:
接受请求 HTTP 标头会通告客户端其能够理解的 MIME 类型
响应标头
Access-Control-Allow-Origin:
一个返回的 HTTP 标头可能会具有 Access-Control-Allow-Origin ,Access-Control-Allow-Origin 指定一个来源,它告诉浏览器允许该来源进行资源访问。
Keep-Alive:
Keep-Alive 表示的是 Connection 非持续连接的存活时间,可以进行指定。
Set-Cookie
Set-Cookie 用于服务器向客户端发送 sessionID。
Expires:
响应过期的日期和时间。
12.怎么与服务端保持连接
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
而HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
建立websocket
实现效果:点击按钮建立连接,页面关闭时关闭连接。
<template>
<div>
<button @click="initSocket">建立websocket连接</button>
</div>
</template>
<script>
export default {
data() {
return {
webSocket: null,
url: '197.2.1.3:8088',
types: '给后台参数'
}
},
methods: {
// 建立连接
initSocket() {
// 有参数的情况下:
let url = `ws://${this.url}/${this.types}`
// 没有参数的情况:接口
// let url1 = 'ws://localhost:9998'
this.webSocket = new WebSocket(url)
this.webSocket.onopen = this.webSocketOnOpen
this.webSocket.onclose = this.webSocketOnClose
this.webSocket.onmessage = this.webSocketOnMessage
this.webSocket.onerror = this.webSocketOnError
},
// 建立连接成功后的状态
webSocketOnOpen() {
console.log('websocket连接成功');
},
// 获取到后台消息的事件,操作数据的代码在onmessage中书写
webSocketOnMessage(res) {
// res就是后台实时传过来的数据
console.log(res);
//给后台发送数据
this.webSocket.send("发送数据");
},
// 关闭连接
webSocketOnClose() {
this.webSocket.close()
console.log('websocket连接已关闭');
},
//连接失败的事件
webSocketOnError(res) {
console.log('websocket连接失败');
// 打印失败的数据
console.log(res);
}
},
created() {
// 页面打开就建立连接,根据业务需要
this.initSocket()
},
destroyed() {
// 页面销毁关闭连接
this.webSocket.close()
},
}
</script>
谨记:在生命周期结束的时候关闭websocket连接,除非业务需要可以不关,不然很耗内存。
destroyed() {
// 页面销毁关闭连接
this.webSocket.close()
},
axios 轮询
实现效果:点击按钮,建立轮询,3秒之后判断状态,成功就关闭,失败就继续发送请求。
<template>
<div>
<button @click="getStatus">发请求拿数据</button>
<span>状态:{{status}}</span>
</div>
</template>
<script>
export default {
data() {
return {
status: ''
}
},
computed: {
// 计算属性
statusData() { return this.status }
},
watch: {
statusData: function (newval) {
// 当返回的新值为创建中的时候,保持3秒轮询
if (newval == 'creating') {
var timer = setInterval(() => {
setTimeout(this.getStatus, 0)
}, 3000)
}
// 当返回的新值为成功的时候,关闭定时器,结束轮询
if (newval == 'success') {
clearInterval(timer)
}
// 当页面关闭的时候,结束轮询,否则就会一直发请求,
//使用$once(eventName, eventHandler)一次性监听事件
this.$once('hook:boforeDestory', () => {
clearInterval(timer)
})
}
},
methods: {
getStatus() {
getStatusApi().then(res => {
if (res.status == 200) this.$message.error('请求失败')
this.status = res.data.status
})
}
},
}
</script>
注意:清除定时器的代码不能写在beforeDestory(){}中,因为路由跳转,不会触发beforeDestory
13.http请求跨域问题及解决方法,JSONP和ajax有什么区别
详细内容见文集《前后端通讯》=>《详解跨域》
ajax是一种发送http请求与后台进行异步通讯的技术。其原理是实例化xmlhttp对象,使用此对象与后台通信。
一个完整的AJAX请求一般包括以下步骤:
(1)实例化XMLHttpRequest对象
(2)连接服务器
(3)发送请求
(4)接收响应数据
jsonp是一种可以实现跨域发送http请求的数据通信格式,可以嵌在ajax中使用。其原理是利用script标签可以跨域链接资源的特性。
JSONP由两部分组成:回调函数和数据,回调函数一般是在浏览器控制,作为参数发往服务器端(当然,你也可以固定回调函数的名字,但客户端和服务器端的名称一定要一致)。当服务器响应时,服务器端就会把该函数和数据拼成字符串返回。
JSONP的请求过程如下:
请求阶段:浏览器创建一个 script 标签,并给其src 赋值。
发送请求:当给script的src赋值时,浏览器就会发起一个请求。
数据响应:服务端将要返回的数据作为参数和函数名称拼接在一起(格式类似”jsonpCallback({name: 'abc'})”)返回。当浏览器接收到了响应数据,由于发起请求的是 script,所以相当于直接调用 jsonpCallback 方法,并且传入了一个参数。
最后:jsonp只支持get请求,ajax支持get和post请求。
另外,相对于CORS,JSONP的优势在于不存在兼容性,支持几乎所有的老浏览器。
14.说下HTTP的报文结构
对于 TCP 而言,在传输的时候分为两个部分:TCP头和数据部分。
而 HTTP 类似,也是header + body的结构,具体而言:
起始行 + 头部 + 空行 + 实体
也可以是下面这种称呼:
请求报文:
请求行,请求头,空行,请求体
响应报文:
状态行,响应头,空行,响应体
由于 http 请求报文和响应报文是有一定区别,因此我们分开介绍。
起始行
对于请求报文来说,起始行类似下面这样:
GET /home HTTP/1.1
也就是方法 + 路径 + http版本。
对于响应报文来说,起始行一般张这个样:
HTTP/1.1 200 OK
响应报文的起始行也叫做状态行。由http版本、状态码和原因三部分组成。
值得注意的是,在起始行中,每两个部分之间用空格隔开,最后一个部分后面应该接一个换行,严格遵循ABNF语法规范。
头部
不管是请求头还是响应头,其中的字段是相当多的,而且牵扯到http非常多的特性,这里就不一一列举的,重点看看这些头部字段的格式:
1.字段名不区分大小写
2.字段名不允许出现空格,不可以出现下划线_
3.字段名后面必须紧接着:
空行
很重要,用来区分开头部和实体。
问: 如果说在头部中间故意加一个空行会怎么样?
那么空行后的内容全部被视为实体。
实体
就是具体的数据了,也就是body部分。请求报文对应请求体, 响应报文对应响应体。
15.说说Get和Post的区别
HTTP 中包括许多方法,Get 和 Post 是 HTTP 中最常用的两个方法,基本上使用 HTTP 方法中有 99% 都是在使用 Get 方法和 Post 方法,所以有必要我们对这两个方法有更加深刻的认识。
get 方法一般用于请求,比如你在浏览器地址栏输入 www.cxuanblog.com 其实就是发送了一个 get 请求,它的主要特征是请求服务器返回资源,而 post 方法一般用于表单的提交,相当于是把信息提交给服务器,等待服务器作出响应,get 相当于一个是 pull/拉的操作,而 post 相当于是一个 push/推的操作。
get 方法是不安全的,因为你在发送请求的过程中,你的请求参数会拼在 URL 后面,从而导致容易被攻击者窃取,对你的信息造成破坏和伪造;
/test/demo_form.asp?name1=value1&name2=value2
而 post 方法是把参数放在请求体 body 中的,这对用户来说不可见。
POST /test/demo_form.asp HTTP/1.1
Host: w3schools.com
name1=value1&name2=value2
get 请求的 URL 有长度限制,而 post 请求会把参数和值放在消息体中,对数据长度没有要求。
get 请求会被浏览器主动 cache,而 post 不会,除非手动设置。
get 请求在浏览器反复的 回退/前进 操作是无害的,而 post 操作会再次提交表单请求。
get 请求在发送过程中会产生一个 TCP 数据包;post 在发送过程中会产生两个 TCP 数据包。对于 get 方式的请求,浏览器会把 http header 和 data 一并发送出去,服务器响应 200(返回数据);而对于 post,浏览器先发送 header,服务器响应 100 continue,浏览器再发送 data,服务器响应 200 ok(返回数据)。
16.什么是无状态协议,HTTP 是无状态协议吗,怎么解决(JWT)
无状态协议(Stateless Protocol) 就是指浏览器对于事务的处理没有记忆能力。举个例子来说就是比如客户请求获得网页之后关闭浏览器,然后再次启动浏览器,登录该网站,但是服务器并不知道客户关闭了一次浏览器。
HTTP 就是一种无状态的协议,他对用户的操作没有记忆能力。可能大多数用户不相信,他可能觉得每次输入用户名和密码登陆一个网站后,下次登陆就不再重新输入用户名和密码了。这其实不是 HTTP 做的事情,起作用的是一个叫做 小甜饼(Cookie) 的机制。它能够让浏览器具有记忆能力。
如果你的浏览器允许 cookie 的话,查看方式 chrome://settings/content/cookies
当你向服务端发送请求时,服务端会给你发送一个认证信息,服务器第一次接收到请求时,开辟了一块 Session 空间(创建了Session对象),同时生成一个 sessionId ,并通过响应头的 Set-Cookie:JSESSIONID=XXXXXXX 命令,向客户端发送要求设置 Cookie 的响应;客户端收到响应后,在本机客户端设置了一个 JSESSIONID=XXXXXXX 的 Cookie 信息,该 Cookie 的过期时间为浏览器会话结束;接下来客户端每次向同一个网站发送请求时,请求头都会带上该 Cookie信息(包含 sessionId ), 然后,服务器通过读取请求头中的 Cookie 信息,获取名称为 JSESSIONID 的值,得到此次请求的 sessionId。这样,你的浏览器才具有了记忆能力。
还有一种方式是使用 JWT 机制,它也是能够让你的浏览器具有记忆能力的一种机制。与 Cookie 不同,JWT 是保存在客户端的信息,它广泛的应用于单点登录的情况。
JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
JWT 具有两个特点
JWT 的 Cookie 信息存储在客户端,而不是服务端内存中。也就是说,JWT 直接本地进行验证就可以,验证完毕后,这个 Token 就会在 Session 中随请求一起发送到服务器,通过这种方式,可以节省服务器资源,并且 token 可以进行多次验证。
JWT 支持跨域认证,Cookies 只能用在单个节点的域或者它的子域中有效。如果它们尝试通过第三个节点访问,就会被禁止。使用 JWT 可以解决这个问题,使用 JWT 能够通过多个节点进行用户认证,也就是我们常说的跨域认证。
JWT的优点:
1.可扩展性好,JWT和session相比,session是保存在服务端的,而jwt是保存在客户端的,使用jwt可以让服务端直接进行平行扩展。
2.无状态,jwt不在服务端存储任何状态,可以明显降低服务器查询数据库的次数。
JWT的缺点:
1.安全性,由于jwt的payload是使用base64编码的,并没有加密,因此jwt中不能存储敏感数据。而session的信息是存在服务端的,相对来说更安全。
2.性能,jwt太长。由于是无状态使用JWT,所有的数据都被放到JWT里,如果还要进行一些数据交换,那载荷会更大,经过编码之后导致jwt非常长,cookie的限制大小一般是4k,cookie很可能放不下,所以jwt一般放在local storage里面。并且用户在系统中的每一次http请求都会把jwt携带在Header里面,http请求的Header可能比Body还要大。而sessionId只是很短的一个字符串,因此使用jwt的http请求比使用session的开销大得多。
3.一次性,无状态是jwt的特点,但也导致了这个问题,jwt是一次性的。想修改里面的内容,就必须签发一个新的jwt。
17.说说你了解的HTTP 的缓存策略
强缓存
服务器使用 Cache-Control 来设置缓存策略,常用 max-age 来表示资源的有效期。
(这里的 max-age 的时间计算起点是响应报文的创建时刻,而不是客户端收到报文的时刻。)
(浏览器也可以发送 Cache-Control 字段,使用 max-age=0 或 no-cache 来刷新数据)
如果想更精确的控制缓存策略,还可以使用 Cache-Control 的其他属性:
no-store:不允许缓存 (用于秒杀页面等变化频率非常高的场景)
no-cache:可以缓存,使用前必须要去服务端验证是否过期,是否是最新版本
must-revalidate:如果缓存不过期就可以继续使用,过期了就必须去服务端验证
强制缓存除了Cache-Control ,还有Expires,但是由于Cache-Control的优先级比expires,那么直接根据Cache-Control的值进行缓存,意思就是说在600秒内再次发起该请求,则会直接使用缓存结果,强制缓存生效。注:在无法确定客户端的时间是否与服务端的时间同步的情况下,Cache-Control相比于expires是更好的选择,所以同时存在时,只有Cache-Control生效。
协商缓存
验证资源是否失效就需要使用条件请求。常用的是 If-Modified-Since 和 If-None-Match,收到 304 状态码就可以复用缓存里的资源。
(If-None-Match 比 If-Modified-Since 优先级更高)
验证资源是否被修改的条件有两个 Last-modified 和 ETag (ETag 比 Last-modified 的精确度更高),需要预先在服务端的响应报文里设置,配合条件请求使用。
18.在你开发的过程中,什么情况下会遇到跨域问题,你是怎么解决的?
- API跨域可以通过服务器上nginx反向代理
- 本地webpack dev server可以设置 proxy,
- new Image, 设src 的时候,图片需要设置Cors
cors需要后台配合设置HTTP响应头,如果请求不是简单请求(1. method:get,post,2. content-type:三种表单自带的content-type,3. 没有自定义的HTTP header),浏览器会先发送option预检请求,后端需要响应option请求,然后浏览器才会发送正式请求,cors通过白名单的形式允许指定的域发送请求
jsonp是浏览器会放过 img script标签引入资源的方式。所以可以通过后端返回一段执行js函数的脚本,将数据作为参数传入。然后在前端执行这段脚本。双方约定一个函数的名称。
联调的时候会需要跨域,线上前端站点域和后台接口不一致也需要跨域,开发时跨域可以通过代理服务器来转发请求,因为跨域本身是浏览器对请求的限制,常见的跨域处理还有JSONP和cors,jsonp是利用脚本资源请求本身就可以跨域的特性,通过与请求一起发送回调函数名,后台返回script脚本直接执行回调,但是由于资源请求是get类型,请求参数长度有限制,也不能进行post请求。cors需要后台配合设置HTTP响应头,如果请求不是简单请求(1. method:get,post,2. content-type:三种表单自带的content-type,3. 没有自定义的HTTP header),浏览器会先发送option预检请求,后端需要响应option请求,然后浏览器才会发送正式请求,cors通过白名单的形式允许指定的域发送请求
同源策略只是浏览器客户端的防护机制,当发现非同源HTTP请求时会拦截响应,但服务器依然处理了这个请求。
服务器端不拦截,所以在同源服务器下做代理,可以实现跨域。
我之前这么看的node中间层处理跨域。
19.什么是HTTP链接的管线化
在使用持久连接的情况下,某个连接上消息的传递类似于
请求1 => 响应1 => 请求2 => 响应2 => 请求3 => 响应3
而管线化是建立在持久连接的基础上的,管线化不再单纯的一次请求后立刻就进行相应,管线化下的持久连接变成了类似于下面这样的:
请求1 => 请求2 => 请求3 => 响应1 => 响应2 => 响应3
只有GET和HEAD请求可以进行管线化,而POST则有所限制。
20.前后端通讯的主要方式
ajax是同源下的交互方式
websocket不限制源
cors是支持跨域,也支持同源,是一种新的通信标准
cors是一个 W3C 标准,全称是“跨域资源共享”(Cross-origin resource sharing)。它允许浏览器向跨域的服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
21.前端请求的常用触发方式
1.form表单
一般表单提交通过type=submit实现,input type="submit",浏览器显示为button按钮,通过点击这个按钮提交表单数据跳转到action指定的路径
<form action="/url.do" method="post">
<input type="text" name="name"/>
<input type="submit" value="提交">
</form>
2.Ajax
Ajax是发出异步HTTP请求的传统方式。
要在Ajax中进行HTTP调用,首先需要初始化一个新XMLHttpRequest()方法的实例,通过实例的open()方法将HTTP方法和URL端点绑定在一起,并调用该send()方法来触发请求。 然后通过监听XMLHTTPRequest.onreadystatechange事件获取readyState的状态,最后根据readyState的状态进行拿到返回数据的逻辑处理。(0.未初始化,1.载入,2.载入完成,3.交互处理,4.完成)
3.Fetch
Fetch是ES6提供的数据请求的方法,它返回一个“Promise”,Promise允许我们以更优雅的方式处理异步请求。
注意一点的是:Fetch不是Ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。
Fetch号称是Ajax的替代品,但是因为其一些缺点,在Vue项目中,我们都会选用体积很小,对原生XHR封装很完善的Axios
4.Axios
Axios 是一个基于Promise 用于浏览器和 Nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范。
22.为什么TCP建立连接不能是两次握手?
如果是两次握手,发送端可以确定自己发送的信息能对方能收到,也能确定对方发的包自己能收到,但接收端只能确定对方发的包自己能收到 无法确定自己发的包对方能收到
并且两次握手的话, 客户端有可能因为网络阻塞等原因会发送多个请求报文,延时到达的请求又会与服务器建立连接,浪费掉许多服务器的资源。
23.为什么TCP断开连接挥手需要四次?
服务端在收到客户端断开连接Fin报文后,并不会立即关闭连接,而是先发送一个ACK包先告诉客户端收到关闭连接的请求,只有当服务器的所有报文发送完毕之后,才发送FIN报文断开连接,因此需要四次挥手。