计算机网络沉淀心得

计算机网络沉淀心得

OSI七层网络模型

结构总述

  • 网络接口层/数据链路层

    • 物理层 -> IEEE820.1

    • 数据链路层 -> FDDO,Ethernet,PPP

  • 网络层

    • 网络层 -> IP,ICMP,ARP,RIP
  • 传输层

    • 传输层 ->TCP,UDP
  • 应用层

    • 会话层 ->SSL,TLS

    • 表示层 -> JPEG,ASCII,DECOIC,加密

    • 应用层 -> HTTP,FTP,SNMP,DNS

物理层

物理层是直接与物理介质打交道的

在这一层光,电,无线电波获取传送信号,电压,转换成数字信号,在这一层主要传输比特流

物理层设备:

  • 网卡

  • 网线

  • 集线器,中继器

  • 调制解调器

物理层信道:

  • 明线(有线导线)

  • 对称电缆

  • 同轴电缆(最广泛)

  • 光纤(光信号传导信号)

  • 无线电波(WiFi,卫星)

数据链路层

功能: 建立逻辑连接,进行硬件地址选址,差错检验.将比特组合成字节进而合成帧(数据帧),使用MAC地址访问介质,发现错误但不能纠正。

MAC地址: 每个网卡的唯一标识

设备:

  • 交换机

网络层

网络层是最复杂的一层,在这一层就定义了我们的IP。该层控制数据链路层与传输层之间的信息转发,建立、维持和终止网络的连接。具体地说,数据链路层的数据在这一层被转换为数据包,然后通过路径选择、分段组合、顺序、进/出路由等控制,将信息从一个网络设备传送到另一个网络设备

IP网址的原因:

在数据链路层,如果所有的使用互联网的用户在同一个网段中,会产生广播风暴,所以要将用户进行划分,让他们在不同的网段中,自己在自己的小网段中广播。而互联网就是这无数的子网络构成的一个巨型网络。

在网络层中引入了一套新的地址,让我们能够区分不同的网段。这套地址就叫做“网络地址”,简称“网址”。于是,”网络层”出现以后,每台计算机有了两种地址,一种是MAC地址,另一种是网络地址。两种地址之间没有任何联系,MAC地址是绑定在网卡上的,网络地址则是管理员分配的,它们只是随机组合在一起。

网络地址帮助我们确定计算机所在的子网络,MAC地址则将数据包送到该子网络中的目标网卡。因此,从逻辑上可以推断,必定是先处理网络地址,然后再处理MAC地址。

功能:

  • 寻址:对网络层而言使用IP地址来唯一标识互联网上的设备,网络层依靠IP地址进行相互通信(类似于数据链路层的MAC地址)

  • 路由:在同一个网络中的内部通信并不需要网络层设备,仅仅靠数据链路层就可以完成相互通信,对于不同的网络之间相互通信则必须借助路由器等三层设备。

设备:

  • 路由器

协议:

  • IPv4

  • IPv6

传输层

功能:

  • 定义端口号

  • 控流

  • 校验

协议:

  • TCP:面向连接的可靠协议,三次握手四次挥手

  • UDP:不可靠协议,但效率更高

会话层

功能:

会话层,是在发送方和接收方之间进行通信时创建、维持、之后终止或断开连接的地方,与电话通话有点相似。

会话层定义了一种机制,允许发送方和接收方启动或停止请求会话,以及当双方发生拥塞时仍然能保持对话。

会话层包含了一种称为检查点(Checkpoint)的机制来维持可靠会话。

检查点定义了一个最接近成功通信的点,并且定义了当发生内容丢失或损坏时需要回滚以便恢复丢失或损坏数据的点,即断点下载的原理。

这一层经常被叫报文

表示层

功能:

安全、压缩、编解码相关的功能和标准。

  • ASCII,utf-8

  • JPEG

这一层经常被叫报文

应用层

功能: 负责为用户和应用程序提供网络服务,直接与用户交互。常见的协议有 HTTP(超文本传输协议)、FTP(文件传输协议)、SMTP(邮件传输协议)等。

协议:

  • HTTP/HTTPS

  • DNS

  • SMTP

  • WebSocket

  • SSH

TCP三次握手

pZR9Z7T.webp

  1. seq(sequence number),序列号随机生成

  2. ack(acknowledgement number)确认号ack=seq + 1

  3. ACK(acknowledgement)确认序列号有效

  4. SYN(Synchronous)发起新连接

过程:

  1. 首先客户端会发送一个段:SYN报文,想跟服务端进行连接,并且会携带一个序列号seq,下次发送的数据序列号还会进行+1。此时客户端发送SYN = 1 seq=x

  2. 服务端收到了SYN + seq 字段之后,服务端也会生成一个对应服务端seq序列号,这时候就会携带ACK确认号,表示之前的SYN 收到了,还会有一个小写的ack 把 客户端的seq + 1,此时服务端发送SYN = 1,ACK = 1,seq = y,ack=x+1

  3. 客户端收到服务端的响应之后会发送一个ACK确定序列号有效,并且还会发送seq,这里的seq会通过算法计算出来是否跟服务端的ack值相等,然后会发送一个新的ack这里的ack是服务端的seq值+1,确保一切正常。此时客户端发送ACK= 1 seq = x+1,ack = y+1

总结:

TCP 三次握手用于在数据传输前建立可靠连接,主要目的是确认双方的收发能力并同步初始序列号。
第一次握手由客户端发送 SYN,请求建立连接;
第二次握手服务器回复 SYN+ACK,确认客户端请求并发送自己的初始序列号;
第三次握手客户端发送 ACK,确认服务器的 SYN。
至此双方都确认了彼此的发送和接收能力,连接正式建立。

TCP四次挥手

pZRCgqx.webp

  1. seq(sequence number),序列号随机生成

  2. ack(acknowledgement number)确认号ack = seq + 1

  3. ACK(acknowledgement)确认序列号有效

  4. SYN(synchronous)发起新连接

  5. FIN(FINISH)完成

  6. 断开连接服务端和客户端都可以主动发起我们拿客户端举例,客户端进行断开操作先发送FIN包生成客户端的seq序列号随后进入wait1状态,这是第一次挥手。客户端发送FIN=1 seq=u

  7. 服务端收到FIN包表示自己进入了关闭等待状态,然后向客户端使用ack验证,验证成功打上ACK标记,随后生成服务端的seq值发送给客户端,这是第二次挥手,服务端此时还可以发送未完成的数据。服务端发送ACK=1 ack=u+1

  8. 等待服务端所有任务操作完成之后服务端开始进入最后确认状态,向客户端发送FIN包,并且验证ack,使用客户端第一次的seq + 1去验证,验证成功打上ACK标记,并且生成一个新的序列号seq发送给客户端,这是第三次挥手。客户端发送FIN seq=v ack=u+1

  9. 客户端收到之后进入超时等待状态2MSL(1-4分钟),经过等到后客户端关闭连接,而服务端收到信息验证完成ack成功之后打上ACk标记随后将关闭连接。服务端发送ACK=1 seq=u+1 ack=v+1

TIME_WAIT 的两个核心作用

  1. 确保最后一个 ACK 能被服务器接收
  • 如果服务器没收到 ACK,会重发 FIN

  • 客户端在 TIME_WAIT 状态仍能正确响应

  1. 防止旧连接的报文污染新连接
  • 等待网络中所有“旧报文”自然消失

  • 时间长度 = 2 × MSL(最大报文生存时间)

总结:

TCP 四次挥手用于可靠地释放连接。由于 TCP 是全双工协议,连接的两个方向需要分别关闭。
主动关闭方首先发送 FIN 表示不再发送数据;被动关闭方回复 ACK 确认;待其数据发送完毕后再发送 FIN;最后主动关闭方发送 ACK 确认。
主动关闭方进入 TIME_WAIT 状态,以确保连接可靠关闭并防止旧报文干扰新连接。

浏览器输入url后发生了什么

URL(统一资源定位符)

http::访问协议

www.server.com:服务器名称/域名

/dir1/:路径名,目录名

file1.html:文件名

DNS解析

DNS将IP地址与域名进行映射,便于用户记忆和访问.

浏览器自身DNS->操作系统DNS->本地host文件->向域名服务器发送请求

过程:

  1. 请求发起后浏览器首先会解析这个域名,首先查看本地硬盘的hosts文件,查看是否存在这个域名对应的规则,如果有的话,就直接使用hosts文件里面的IP地址

  2. 如果在本地的hosts文件中没有找到对应的IP地址,浏览器会发出一个DNS请求到本地DNS服务器,本地DNS服务器一般由ISP(网络接入服务商)提供。

  3. 查询你输入的网址的DNS请求到达本地DNS服务器后,本地DNS服务器会首先查询它的缓存记录,如果缓存命中则直接返回结果,此过程是递归方式进行查询,如果没有,本地服务器还需要向DNS根服务器进行查询。

  4. 根DNS服务器没有记录具体的域名和IP地址的对应关系,而是告诉本地DNS服务器可以到域服务器上继续查询,并给出域服务器的地址,这个过程是迭代的过程。

一、核心概念:什么是 OPTIONS 请求?
OPTIONS 是 HTTP 的一种请求方法,用于获取服务器支持的通信选项。

在浏览器 CORS(跨域资源共享) 场景中,OPTIONS 被用作 “预检请求”(Preflight Request)

预检请求的目的是为了确保实际请求对目标服务器是安全的,发送预请求可以得知服务器是否允许跨域请求以及运行那些字段和HTTP方法。
二、两种 CORS 请求类型


类型 英文
简单请求 Simple Request
复杂请求 Complex Request / Preflighted Request

三、简单请求的判定标准(必须同时满足

  1. 方法限制

只能是以下之一:

  • GET

  • HEAD

  • POST

    1. 头部限制

只能包含 CORS 安全列出的头部

  • Accept

  • Accept-Language

  • Content-Language

  • Content-Type(但值受限,见下)

  1. Content-Type 限制(如果是 POST)

只能是:

  • application/x-www-form-urlencoded

  • multipart/form-data

  • text/plain

  1. 无自定义头部

不能添加如 X-Custom-HeaderAuthorization 等自定义头部

  1. 无 ReadableStream 对象

请求中不能使用 ReadableStream

普通表单提交、简单的 GET 请求
四、复杂请求(触发预检的场景)


只要 违反上述任一条件,就是复杂请求:

场景 示例
使用非简单方法 PUTDELETEPATCH
发送 JSON 数据 Content-Type: application/json
携带自定义头部 Authorization: Bearer token
使用特殊头部 X-Requested-With 等

协商缓存

强制缓存

浏览器强制缓存服务端提供的资源

通过配置响应头的cache-control字段的max-ageExpires字段来决定

头部 语法 特点 状态码
Expires Expires: Wed, 21 Oct 2026 07:28:00 GMT HTTP/1.0 产物,绝对时间,受本地时间影响 200 (from disk cache)
Cache-Control Cache-Control: max-age=31536000 HTTP/1.1 标准,相对时间(秒),更可靠 200 (from memory/disk cache)

协商缓存

当服务端发现资源最后修改时间Last-ModifiedIf-modified-since值相等,代表资源从该时间后再未改变过。

服务端于是返回304(Not Modified)状态码,表示资源没有改变,并且响应体为空。浏览器拿到后,就知道原本可能过期的缓存其实还可以继续使用。

如果资源改变了,就会返回200,且响应体带上最新资源。Etag 的值没有规定一般是文件hash,当然你也可以设置版本号之类的去对比 

E-Tag一般规定为文件hash,也可以设置版本号。

头部 语法 验证方式 精度 状态码
Last-Modified Last-Modified: Tue, 15 Nov 2024 12:45:26 GMT 对比修改时间 秒级 304 / 200
ETag ETag: "33a64df5-8d5c-4c7a-9c3f-2e1b8d6f5a4c" 对比内容指纹(哈希) 毫秒级 304 / 200

缓存规则

先强制,后协商;
强制不过期,直接本地拿;
强制过期问服务器,ETag 优先来比对;
ETag 相同 304,不同就下新资源。

HTML渲染

  1. HTML解析器把超文本和标签通过AST解析为DOM树

  2. 把CSS样式表转化为浏览器可以理解的styleSheet,属性值标准化,再处理集成和层叠,成为CSSOM的构建过程计算出DOM节点的样式

回流与重绘

Render Treez中部分或全部元素的尺寸、结构或某些属性发生改变的时候,浏览器重新渲染部分或全部文档的过程称之为回流

触发回流的操作

  • 页面首次渲染

  • 浏览器窗口大小发生改变

  • 元素尺寸或位置发生改变

  • 元素内容变化

  • 元素字体大小变化

  • 添加或删除可见的DOM元素

  • 激活CSS伪类

  • 查询某些属性或调用方法

常用且会导致回流的属性和方法:

会导致回流的属性和方法

  • clientWidth/Height/Top/Left:元素的可视区域尺寸

  • offsetWidth/Height/Top/Left:元素的完整尺寸

  • scrollWidth/Height/Top/Left:元素的实际内容尺寸(包括由于溢出而不可见的部分)

  • scrollIntoView():将元素滚动到视口中使其可见

  • scrollIntoViewIfNeeded():非标准方法(仅WebKit/Blink支持)

  • getComputedStyle():返回元素的所有CSS属性的计算值

  • getBoundingClientRect():返回元素的大小及其相对于视口的位置,返回一个包含lefttoprightbottomwidthheight的DOMRect对象

  • scrollTo():将元素或窗口滚动到指定位置

触发重绘的操作

当页面中元素样式的改变并不影响它在文档流中的位置时color,background-color,visibility

为什么transform/opacity不触发回流

  • 回流/重排(Reflow): 发生在布局阶段

  • 重绘(Repaint): 发生在绘制阶段

  • 合成(Composite): 发生在合成阶段

浏览器会为这些属性创建独立的合成层

  • 元素被提升到自己的图层(layer)

  • 图层由GPU直接处理,不依赖CPU的布局计算

  • 图层可以独立于其他图层进行变换

浏览器自动创建合成层的情况:

  • 3D/透视变换(perspective, transform3d)

  • 使用will-change: transform/opacity

  • 视频、canvas、iframe元素

  • 有3D上下文或加速2D上下文的canvas

  • 具有opacity动画的过渡元素

如何避免回流

1. 开发阶段原则

  • 优先使用CSS动画而非JavaScript动画

  • 使用transform/opacity实现视觉变化

  • 避免直接操作内联样式

  • 批量读取和写入DOM属性

  • requestAnimationFrame()将DOM操作安排在浏览器重绘之前

2. 架构设计原则

  • 实现虚拟列表/无限滚动

  • 采用组件懒加载

  • 实现代码分割和按需加载

CDN

如果配置了CDN,DNS会将最终的域名解析权交给CNAME(别名指向)指向的CDN专用DNS服务器。

浏览器跨域

为什么会有跨域?

同源策略: 相同网址的请求,其协议、域名、端口都应该相同,否则均属于跨域。

1. 防止跨站脚本攻击(XSS)

如果没有同源策略,恶意网站可以:

  • 通过iframe加载银行网站

  • 使用JavaScript读取银行页面的DOM内容

  • 窃取用户的登录凭证、账户信息

2. 防止跨站请求伪造(CSRF)

同源策略限制了跨域读取响应,使得CSRF攻击虽然能发送请求,但攻击者无法读取响应内容。

3. 保护用户会话状态

  • 浏览器为每个源维护独立的cookie存储

  • 防止恶意网站读取或修改其他网站的cookie

  • 确保会话隔离,用户在不同网站的登录状态互不干扰

4. 防止恶意数据窃取

  • 阻止恶意网站读取其他网站的本地存储(localStorage、sessionStorage)

  • 防止IndexedDB等客户端数据库被跨域访问

  • 保护用户的浏览历史、缓存等敏感信息

跨域解决方案

前后端协商JSONP

原理: Script标签的src不受同源策略的限制,可以跨域访问请求数据,但只能发送get请求

缺点: 只能发送GET请求,不安全,不容易维护

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<html>
<head>
<meta title="CORS">
<meta charset="utf-8">
</head>
<body>

</body>
<script>
const jsonp = (name) =>{
let script = document.createElement('script');
script.src = `http://localhost:3000/jsonp?callback=${name}`;
document.body.appendChild(script);
return new Promise((resolve)=>{
window[name] = (data) =>{
resolve(data)
}
})
}
jsonp(`callback${new Date().getTime()}`).then(data=>{
console.log(data);
})
</script>
</html>

后端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import express from'express'

const app = express()

app.get('/jsonp',(req,res)=>{
const {callback} = req.query

res.send(`${callback}(${JSON.stringify({message:'Hello, JSONP!'})})`)

})

app.listen(3000,()=>{
console.log('JSONP server running on http://localhost:3000')})

前端代理

使用Vite,Webpac配置Proxy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// vite.config.ts


import {defineConfig} from 'vite'


export default defineConfig({
server:{
proxy:{
'/api':{
target:'http://localhost:3000',
changeOrigin:true,
// rewrite...
}
}
}
})

后端配置请求头

  1. Access-Control-Allow-Origin:控制哪些源可以访问

  2. Access-Control-Allow-Credentials:是否允许携带凭证

  3. Access-Control-Allow-Methods:允许的HTTP方法

  4. Access-Control-Allow-Headers:允许的请求头

1
2
3
4

app.get('api/json',(res,req)=>{
res.setHeader('Access-Control-Allow-Origin',"*");
})

Nginx

配置Nginx

1
2
3
location /api {
proxy_pass http://127.0.0.1:3000;
}

AJAX

Ajax(Asynchronous JavaScript And XML)即异步 JavaScript 和 XML,是一组用于在网页上进行异步数据交换的Web开发技术,可以在不刷新整个页面的情况下向服务器发起请求并获取数据,然后将数据插入到网页中的某个位置。这种技术能够实现增量式更新页面,提高用户交互体验,减少响应时间和带宽的消耗。

使用 Ajax 技术,可以通过 JavaScript 和 XMLHttpRequest 对象来向服务器获取数据。在Ajax请求的过程中,可以通过定义回调函数来对请求的结果进行处理,回调函数会在请求完成后执行,通过这种方式可以更新页面内容或者响应用户操作。

GET请求

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
<html>
<head>
<meta title="CORS">
<meta charset="utf-8">
</head>
<body>
<button id="btn">AJAX GET</button>
<p id="updatedP"> It should update.</p>
</body>
<script>
const btn = document.getElementById('btn');
const sendAjax = () =>{
const xhr = new XMLHttpRequest();
xhr.open('GET','http://localhost:3000/api/hello',true);
xhr.onreadystatechange = () => {
if(xhr.readyState === 4 && xhr.status === 200){
const res = xhr.responseText;
document.getElementById('updatedP').innerText = res;
console.log(res);
}
}
xhr.send(null);
}
btn.addEventListener('click',()=>{
sendAjax();
});


</script>
</html>

发送POST请求

1
2
3
4
5
6
7
8
9
10
11
12
13
const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:3000/api/post')
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
if (xhr.status === 200) {
document.querySelector('#result').innerText = xhr.responseText;
}
else {
console.log('Request failed. Returned status of ' + xhr.status);
}
};
xhr.send(JSON.stringify({name: 'zhangsan', age: 18}));

POST 请求 application/x-www-form-urlencoded

1
2
3
4
5
6
7
8
9
10
11
12
13
const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:3000/api/post')
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function() {
if (xhr.status === 200) {
document.querySelector('#result').innerText = xhr.responseText;
}
else {
console.log('Request failed. Returned status of ' + xhr.status);
}
};
xhr.send('name=zhangsan&age=18');

中断请求 和 设置超时时间

中断请求只需要调用 xhr.abort(); 即可并且会有一个中断的回调。

1
xhr.addEventListener('abort', function (event) { console.log('我被中断了'); });

超时时间可以设置timeout 参数

xhr.timeout = 3000;

同样有一个超时回调

1
xhr.addEventListener('timeout', function (event) { console.log('超时啦'); });

获取进度

可以监听 progress

在监听器中,我们通过 event.loaded 和 event.total 属性获取已上传数据量和总数据量,并计算上传进度,最后将进度显示在页面上

Fetch API

为什么使用Fetch:

  • 代码更简单

  • 可维护性好

GET请求

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
<html>
<head>
<meta title="CORS">
<meta charset="utf-8">
</head>
<body>
<button id="btn">AJAX GET</button>
<p id="updatedP"> It should update.</p>
</body>
<script>
const btn = document.getElementById('btn');
const sendfetch = () =>{
fetch('http://localhost:3000/api/hello')
//指定返回方式
.then(res=>res.text())
.then(data=>{
const p = document.getElementById('updatedP');
p.innerText = data;
})
}
btn.addEventListener('click',()=>{
sendfetch();
});


</script>
</html>

POST请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

fetch('http://localhost:3000/api/post',{
method:'POST',
headers:{
'Content-Type':'application/json'
},
body:JSON.stringify({
name:'zhangsan',
age:18
})
}).then(res => {
console.log(res);
return res.json()
}).then(res => {
console.log(res);
})

中断请求

使用 AbortController 的 abort方法中断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const abort = new AbortController()
fetch('http://localhost:3000/api/post',{
method:'POST',
headers:{
'Content-Type':'application/json'
},
signal:abort.signal,
body:JSON.stringify({
name:'zhangsan',
age:18
})
}).then(res => {
console.log(res);
return res.json()
}).then(res => {
console.log(res);
})

document.querySelector('#stop').addEventListener('click', () => {
console.log('stop');
abort.abort()
})

获取进度

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

const btn = document.querySelector('#send')
const sendFetch = async () => {
const data = await fetch('http://localhost:3000/api/txt',{
signal:abort.signal
})
//fetch 实现进度条
const response = data.clone()
const reader = data.body.getReader()
const contentLength = data.headers.get('Content-Length')
let loaded = 0
while (true) {
const { done, value } = await reader.read()
if (done) {
break
}
loaded += value?.length || 0;
const progress = document.querySelector('#progress')
progress.innerHTML = (loaded / contentLength * 100).toFixed(2) + '%'
}
const text = await response.text()
console.log(text);
}
btn.addEventListener('click', sendFetch)

携带Cookie

设置 credentials:'include'

SSE

概述

SSE(Server-Sent Events)是一种用于实现服务器主动向客户端推送数据的技术,也被称为“事件流”(Event Stream)。它基于 HTTP 协议,利用了其长连接特性,在客户端与服务器之间建立一条持久化连接,并通过这条连接实现服务器向客户端的实时数据推送。

SSE与WS的区别

SSE(Server-Sent Events)和 WebSocket 都是实现服务器向客户端实时推送数据的技术,但它们在某些方面还是有一定的区别。

  1. 技术实现

SSE 基于 HTTP 协议,利用了其长连接特性,通过浏览器向服务器发送一个 HTTP 请求,建立一条持久化的连接。而 WebSocket 则是通过特殊的升级协议(HTTP/1.1 Upgrade 或者 HTTP/2)建立新的 TCP 连接,与传统 HTTP 连接不同。

  1. 数据格式

SSE 可以传输文本和二进制格式的数据,但只支持单向数据流,即只能由服务器向客户端推送数据。WebSocket 支持双向数据流,客户端和服务器可以互相发送消息,并且没有消息大小限制。

  1. 连接状态

SSE 的连接状态仅有三种:已连接、连接中、已断开。连接状态是由浏览器自动维护的,客户端无法手动关闭或重新打开连接。而 WebSocket 连接的状态更灵活,可以手动打开、关闭、重连等。

  1. 兼容性

SSE 是标准的 Web API,可以在大部分现代浏览器和移动设备上使用。但如果需要兼容老版本的浏览器(如 IE6/7/8),则需要使用 polyfill 库进行兼容。而 WebSocket 在一些老版本 Android 手机上可能存在兼容性问题,需要使用一些特殊的 API 进行处理。

  1. 安全性

SSE 的实现比较简单,都是基于 HTTP 协议的,与普通的 Web 应用没有太大差异,因此风险相对较低。WebSocket 则需要通过额外的安全措施(如 SSL/TLS 加密)来确保数据传输的安全性,避免被窃听和篡改,否则可能会带来安全隐患。

总体来说,SSE 和 WebSocket 都有各自的优缺点,适用于不同的场景和需求。如果只需要服务器向客户端单向推送数据,并且应用在前端的浏览器环境中,则 SSE 是一个更加轻量级、易于实现和维护的选择。而如果需要双向传输数据、支持自定义协议、或者在更加复杂的网络环境中应用,则 WebSocket 可能更加适合。

API

EventSource构造函数

EventSource 的构造函数接收一个 URL 参数,通过该 URL 可以建立起与服务器的连接,并开始接收服务器发送的数据。

1
const eventSource = new EventSource('/my-server');

EventSource.readyState 属性

readyState 属性表示当前 EventSource 对象的状态,它是一个只读属性,它的值有以下几个:

  • CONNECTING:表示正在和服务器建立连接。
  • OPEN:表示已经建立连接,正在接收服务器发送的数据。
  • CLOSED:表示连接已经被关闭,无法再接收服务器发送的数据。

EventSource.close() 方法

close() 方法用于关闭 EventSource 对象与服务器的连接,停止接收服务器发送的数据。

EventSource.onopen 事件

onopen 事件表示 EventSource 对象已经和服务器建立了连接,并开始接收来自服务器的数据。当 EventSource 对象建立连接时,触发该事件。

eventSource.onopen = function(event) { console.log('连接成功!', event); };

EventSource.onerror 事件

onerror 事件表示在建立连接或接收服务器数据时发生了错误。当出现错误时,触发该事件。

eventSource.onerror = function(event) { console.log('发生错误:', event); };

EventSource.onmessage 事件

onmessage 事件表示已经接收到服务器发送的数据,当接收到数据时,触发该事件。

eventSource.onmessage = function(event) { console.log('接收到数据:', event); };

以上就是 EventSource 对象的常用 API 介绍,需要注意的是,在使用 EventSource 对象的过程中,如果服务器没有正确地设置响应头信息(如:Content-Type: text/event-stream),可能会导致 EventSource 对象无法接收到服务器发送的数据。

概念

在 web 开发中,我们经常需要将用户行为或性能数据上报到服务器。为了不影响用户体验,开发者通常会在页面卸载时进行数据上报。然而,传统的数据上报方式,如 XMLHttpRequest 或 Fetch API,容易受到页面卸载过程中的阻塞,导致数据丢失。为了解决这个问题,navigator.sendBeacon API 被引入,它可以在页面卸载时安全、可靠地发送数据。

应用场景

  1. 发送心跳包,保持服务器长连接

  2. 埋点,在页面卸载或关闭时记录用户在线时间,pv uv,以及错误日志上报。

  3. 发送用户反馈,发送用户反馈信息。

优点

  1. 不受页面卸载过程的影响,确保数据可靠发送

  2. 异步执行,不阻塞页面关闭或跳转

  3. 能够发送跨域请求

缺点

  1. fetchAJAX都可以发送任意请求,sendBeacon只能发送POST

  2. ~可以传输任意字节,sendBeacon只能传输少量数据

  3. ~可以定义任意请求头,sendBeacon无法自定义请求头

  4. sendBeacon只能传输ArrayBufferArrayBufferViewBlobDOMStringFormDataURLSearchParams

  5. 处于危险网络环境或开启广告屏蔽插件则无法使用。

HTTP/HTTPS

HTTPS

HTTPS,全称为HypertextTransferProtocol Secure,是一种通过加密通道传输数据的安全协议。它是HTTP协议的安全版本,用于在Web浏览器和Web服务器之间进行安全的数据传输。HTTPS在传输过程中使用了 SSL(Secure Sockets Layer)或TLS(TransportLayer Security)协议来加密数据,确保敏感信息在传输过程中不会被窃取或篡改。 

TLS/SSL

TLS和SSL是用于网络通信协议的安全协议,提供了加密和认证机制,用于确保数据传输的机密性和完整性。该协议位于应用层和传输层之间

主要作用:

  1. 加密通信:使用加密算法加密数据,防止第三方截获和窃听通信内容。

  2. 身份认证:提供了身份验证机制,用于确认通信双方的身份,并确保数据只发送到正确的接收方。

SSL是最早实现HTTPS的协议,现已被TLS取代,TLS解决了SSL存在的安全漏洞,改进了算法。

加密

  1. 对称加密:AES、DES

  2. 非对称加密:RSA DSA,公钥可以公开,私钥只能让服务端知道。

JWT(Json Web Token)

组成

头部由两部分组成: 令牌类型和签名算法。

1
2
3
4
{
"alg":"HS256",
"typ": "JWT"
}

Payload

Payload包含所要传递的信息,如用户身份、权限等

1
2
3
4
{
"iss":"example@email.com",
"exp": "..."
}

Signature

使用私钥对头部和负载进行加密,用于验证令牌完整性和真实性。

_Base64UrlEncode(Header) + "." + Base64UrlEncode(Payload)_


计算机网络沉淀心得
http://arkpln.github.io/3712793328.html
Author
FangZhou
Posted on
January 26, 2026
Licensed under