前端知识总结

网络相关

HTTP 、 HTTP 0.9 、 HTTP 1.0 、 HTTP 1.1 和 HTTP 1.1

HTTP 是一种协议,全称超文本传输协议(英文:Hyper Text Transfer Protocol)。它是一种构建在 TCP/IP 之上的应用层协议。主要用于实现客户端和服务端的沟通。

五层网络结构主要包括:应用层、传输层、网络层、数据链路层、物理层。

HTTP的报文结构
HTTP 是基于 TCP 的,而 TCP 在传输时分为: TCP 头和数据部分。

HTTP 请求报文由四部分组成:

  • 请求行
  • 头部
  • 空行
  • 请求体

请求行
请求行由三部分组成:

  • 请求方法
  • 请求url(不包括域名)
  • HTTP 协议版本
1
GET /home HTTP/1.1

请求方法

序号 方法 描述 定义方法的协议
1 GET 请求指定页面的信息,返回实体主体 HTTP 1.0
2 HEAD 类似于GET请求,只不过返回的响应没有具体内容,用于获取报头 HTTP 1.0
3 POST 向指定资源提交数据进行处理请求,数据包含在请求体中。POST请求可能会导致新的资源的建立或已有资源的修改 HTTP 1.0
4 PUT 从客户端向服务器传送的数据取代指定文档的内容 HTTP 1.1
5 DELETE 请求服务器删除指定的页面 HTTP 1.1
6 CONNECT HTTP 1.1 协议中预留给能够将连接改为管道方式的代理服务器 HTTP 1.1
7 OPTIONS 允许客户端查看服务器的性能 HTTP 1.1
8 TRACE 回显服务器收到的请求,主要用于测试或诊断 HTTP 1.1
9 PATCH 是对PUT方法的补充,用来对已知资源进行局部更新 HTTP 1.1

请求头部
主要由键值对组成,每行一对。主要有:

  • User-Agent: 产生请求的浏览器类型
  • Accept:客户端希望接受的数据类型
  • Content-Type:发送端发送的实体的数据类型
  • Host:请求的主机名

常见的Content-Type:

Content-Type 解释
text/html html格式
text/plain 纯文本格式
text/css css格式
text/javascript JavaScript格式
image/gif gif图片格式
image/jepg jpg图片个式
image/png png图片格式
application/x-www-form-urlencoded POST提交表单的默认方式,from表单序列化成键值对发送到服务器
application/json POST用来告诉服务端消息的主体是序列化后的JSON字符串
text/xml POST发送xml数据
multipart/from-data POST发送二进制数据,主要用于文件上传

空行
请求头之后是空行,告诉服务端不再有请求头,用来区分头部和实体

请求体 对应的就是具体的数据,就是body部分。

HTTP 响应报文由三部分组成:

  • 状态行
  • 响应头部
  • 空行
  • 内容实体

状态行

  • 服务器 HTTP 协议版本
  • 响应状态码
  • 状态码文本描述

HTTP 响应状态码分类

分类 分类描述
1** 信息,服务器收到请求,需要请求者继续执行操作
2** 成功,操作成功接收并处理
3** 重定向,需要进一步的操作以完成
4** 客户端错误,请求包含语法错误,无法完成请求
5** 服务器错误,服务器在处理请求的过程中发送了错误

常见 HTTP 状态码列表

状态码 状态码英文名称 中文描述
100 Continue 继续,客户端应继续其请求
101 Switch Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
200 OK 请求成功。一般用于 GET 和 POST 请求
202 Accepted 已接受。已经接受请求,但未处理完成
300 Multiple Choices 多种选择。请求的资源可包括多个位置,相应的可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301 Moved Permanently 永久移动。请求的资源已被永久的移动到新 URI ,返回的信息会包括新的 URI , 浏览器会自动定向到新的 URI ,今后任何新的请求都应使用新的 URI 代替
302 Found 临时移动。与 301 类似,但资源只是临时被移动。客户端应继续使用原 URI
303 See Other 表示资源存在着另一个 URL,应使用 GET 方法获取资源(对于301/302/303响应,几乎所有浏览器都会删除报文主体并自动用GET重新请求)
400 Bad Request 客户端请求的语法错误,服务器无法理解
401 Unauthorized 表示发送的请求需要有通过 HTTP 认证的认证信息
403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
404 Unauthorized 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
500 Internal Server Error 服务器内部错误,无法完成请求
502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503 Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中

HTTP 0.9

  • 1991 年,原型版本,功能简陋,只有一个命令 GET ,只支持纯文本内容。

HTTP 1.0

  • 任何格式的内容都可以发送,使得互联网不仅可以传输文字,还可以传输图像、视频、二进制等文件。
  • 除了 GET 方法,还引入了 POST 方法 和 HEAD 命令
  • http 请求和回应的格式改变,除了数据部分,每次通信都必须包括头信息,用来描述元数据
  • 只使用 header 中的 if-Modified-Since 和expires 作为缓存失效的标志
  • 不支持断点续传,也就是说,每次都会传送全部的页面和数据
  • 通常每台计算机只能绑定一个IP,所有请求消息的URL并没有传递主机名

HTTP 1.1

  • 引入持久连接TCP 连接默认不关闭,可以被多个请求复用,不用声明 Connection: keep-alive。长连接的连接时长可以通过请求头中的 keep-alive 来设置
  • 引入管道机制,在同一个 TCP 连接里,客户端可以同时发送多个请求,进一步改进了HTTP协议的效率
  • HTTP 1.1 中增加了 E-tagIf-Unmodified-SinceIf-MatchIf-None-Mathch 等缓存控制标头来控制缓存失败
  • 支持断电续传,通过使用请求头中的 Range 来实现
  • 使用了虚拟网络,在一台物理服务器上可以存在多个虚拟主机,共享一个 IP 地址
  • 新增 PUTPATCHOPTIONSDELETE 方法

HTTP 1.x版本问题

  • 在传输数据过程中,所有内容都是明文,客户端和服务器端都无法验证对象的身份,无法保证数据的安全性
  • HTTP 1.1 版本默认允许复用 TCP 连接,但是在同一个 TCP 连接里,所有数据通信是按次序进行的,服务器通常在处理完一个回应后,才会继续处理下一个,造成队头阻塞
  • HTTP 1.x 版本支持 keep-alive ,用此方案来弥补创建多次产生的延迟,但同样会给服务器带来压力。

HTTP 2.0

  • 二级制帧。这是一次彻底的二进制协议,头信息和数据体都是二进制,并且统称为数据帧
  • 头部压缩HTTP 1.1 版本会出现头部,头部会占用几百甚至几千字节,而请求体经常只有几十字节,导致头部偏重的情况,HTTP 2.0 采用 HPACK 算法进行压缩
  • 多路复用。复用 TCP 连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,不用按顺序一一对应,解决队头阻塞的问题
  • 服务器推送,允许服务器未经请求,主动向客户端发送资源,即服务器推送
  • 请求优先级,可以设置数据帧的优先级,让服务端先处理重要资源,优化用户体验

TCP 三次握手

  • 第一次握手:客户端发送初始序号seq = xSYN=1的请求标志。此时服务器得知客户端发送正常,自己接收正常。
  • 第二次握手:服务器发送请求标志SYN=1,确认标志ACK=1,自己的序号seq=y,发送客户端的确认信号ack=x+1。客户端知道自己发送、接收正常,服务器接收、发送正常。
  • 第三次握手:客户端发送确认信号ACK=1,发送自己的序号seq=x+1,发送对方的确认号ack=y+1。服务器知道客户端发送、接收正常,自己接收、发送也正常。

TCP 四次分手

  • 第一次挥手:客户端发出释放FIN=1,自己序列号seq=u,进入FIN-WAIT-1状态,是客户端的请求断开。
  • 第二次挥手:服务器收到客户端的请求后,发出ACK=1确认标志和客户端的确认号ack=u+1,自己的序列号seq=v,进入CLOSE-WAIT状态,服务器确认客户端的断开请求。
  • 第三次挥手:客户端收到服务器确认结果后,进入FIN-WAIT-2状态。此时服务器发送释放FIN=1信号,确认标志ACK=1,确认序号ack=u+1,自己序号seq=w,服务器进入LAST-ACK(最后确认态),服务器请求断开。
  • 第四次挥手:客户端收到回复后,发送确认ACK=1ack=w+1,自己的seq=u+1,客户端进入TIME-WAIT(时间等待)。客户端经过2个最长报文段寿命后,客户端CLOSE;服务器收到确认后,立刻进入CLOSE状态,客户端确认服务器断开。

为什么连接的时候是三次握手,关闭的时候却是四次挥手?

连接时,当服务端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文,对应用于同步+应答。连接关闭时,当服务端收到FIN报文时,也许还有话要说,并不会立即关闭SOCKET,所以不会立即返回一个FIN,而是先回复一个ACK报文,告诉客户端自己已经收到了FIN,而只有等服务端把要说的话说完,才能发送FIN,因此需要四步。

Connection:keep-alive 是什么

keep-alive 能够使客户端到服务器的连接持续有效。

websocket 知识

websocketHTML5 开始提供的一种浏览器与服务器进行全双工通信的网络技术,属于应用层协议。它基于 TCP 传输协议,复用 HTTP 的握手通道。

websocket 的优点:

  • 支持双向通信,实时性更强
  • 更好的二进制支持
  • 较少的开销
  • 支持拓展
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 客户端建立 websocket 连接
const websocket = null
if('WebSocket' in window){
websocket = new WebSocket("ws://ip:port/test");
}
websocket.onopen = function(){
console.log("连接成功");
}


websocket.onclose = function(){
console.log("退出连接");
}


websocket.onmessage = function (event){
console.log("收到消息"+event.data);
}


websocket.onerror = function(){
console.log("连接出错");
}

window.onbeforeunload = function () {
websocket.close(num);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// 服务端搭建 websocket
// 已连接的客户端
let clients = new Array()
const WebSocket = require('ws')
// 启动端口为8888
const wss = new WebSocket.Server({ port: 8001 });
wss.on('listening', () => {
console.log("【开始监听】:websocket server");
})
wss.on('connection', (ws, request) => {
console.log(request.url);
let id = request.url.substring(1)
try {
id = parseInt(id)
} catch (err) {
ws.close()
return
}
console.log(request.headers['sec-websocket-protocol']);
clients[id + 's'] = ws
// 用户连接的提醒
console.log('【建立连接】:当前连接用户数量为:' + Object.keys(clients).length);
// 监听客户端的消息
ws.on('message', (msg) => {
console.log("【收到消息】:" + msg)
let message = null
try {
message = JSON.parse(msg)
} catch (err) {
console.error(err);
clients[id + 's'].send(JSON.stringify({
fromUId: 0,
toUId: id,
type: 'error',
comtent: '您发送的消息格式有误!'
}))
return
}
console.log(clients[`${message.toUId}s`]);
if (message.type == "private" && !clients[`${message.toUId}s`]) {

ws.send(JSON.stringify({
fromUId: 0,
toUId: id,
type: 'error',
comtent: '当前用户不在线'
}))
return
}
message.fromUId = id
if (message.type == 'private') {
clients[`${message.toUId}s`].send(JSON.stringify(message))
} else if (message.type == 'group') {
for (const key in clients) {
clients[key].send(JSON.stringify(message))
}
}
})
// 监听客户端错误
ws.on('error', (err) => {
console.error(err);
})
// 监听客户端断开连接
ws.on('close', () => {
// 客户端断开连接,删除
delete clients[id + 's']
console.log('【退出连接】: 当前连接用户数量为:' + Object.keys(clients).length);
})

})
// 监听服务关闭
wss.on('close', () => {
console.log('wss close');
})

DNS

DNS 协议提供的是一种主机名到 IP 地址的转换服务,就是我们常说的域名系统。是应用层的协议,通常该协议允许在UDP协议之上,使用的是53端口

DNS在本地DNS服务器的查询过程(递归查询)
DNS查找递归查询过程

本地 DNS 服务器向其他域名服务器请求的过程(迭代查询)
DNS迭代查找过程

DNS 为什么使用 UDP 协议作为传输层协议?

DNS 使用 UDP 协议作为传输层协议的主要原因是为了避免使用 TCP 协议时造成的连接时延