chenfei-hnu / Blog

个人整理的跟前端相关的文档 ( This is some front-end development related documentation )
9 stars 2 forks source link

网络传输相关知识 #38

Open chenfei-hnu opened 4 years ago

chenfei-hnu commented 4 years ago

TCP/UDP

UDP 协议是面向无连接的,不保证有序且不丢失的传递到对端 由于UDP的无连接及无拥塞控制,网络不好的情况下可能丢包 相对于TCP协议减小了请求复杂度和大小,更适用于实时性要求高的场景 提供了单播,多播,广播的功能

TCP 建立连接断开连接都需要先需要进行握手 在传输数据的过程中,通过各种算法保证数据的可靠性,相比 UDP 不那么的高效 在报文传输的过程中可能会出现丢包或报文出错的问题,超过超时时间就会请求重传需要再次发送数据直到对端响应,所以需要每次都备份发送的数据


第一次握手
客户端向服务端发送连接请求报文段

第二次握手
服务端收到连接请求报文段后,如果同意连接,则会发送一个应答

第三次握手
当客户端收到连接同意的应答后,还要向服务端发送一个确认报文,服务端收到这个报文后连接建立成功

第三次握手的主要是避免前面的请求阶段超时,导致重传再建立一个连接,超时请求最终到达时,又判断
为需要建立TCP连接,造成服务端始终等待一个TCP连接传输数据,造成资源浪费的问题

客户端:hello,你是server么? 服务端:hello,我是server,你是client么 客户端:yes,我是client

断开链接四次挥手

客户端向服务器发送连接释放请求

服务器收到连接释放请求后,在应用层释放 TCP 链接,不再接收客户端发送的数据

如果服务器此时还有未发送完毕的数据会继续发送,完毕后会向客户端发送连接释放请求

客户端收到释放请求后,进入关闭状态,向服务器发送确认应答,服务器收到应答也进入关闭状态

主动方:我已经关闭了向你那边的主动通道了,只能被动接收了 被动方:收到通道关闭的信息 被动方:那我也告诉你,我这边向你的主动通道也关闭了 主动方:最后收到数据,之后双方无法通信 ——————————————————————

五层因特网协议栈

从客户端发出http请求到服务器接收,中间会经过一系列的流程 从应用层的发送http请求,到传输层通过三次握手建立tcp/ip连接,再到网络层的ip寻址,再到数据链路层的封装成帧,最后到物理层的利用物理介质传输,服务端的接收就是反过来的步骤

网络模型 7层模型 image

——————————————————————

前后端分离

1.接口数据可靠性修复 在中间层做数据处理,修复空数据等后台异常数据

2.使用服务器渲染大幅提高页面渲染的时间和 SEO

3.进行请求的合并整理,缩短请求时间

——————————————————————

GET/POST区别

GET/POST都是TCP连接,GET产生一个TCP数据包,POST产生两个TCP数据包 POST请求时,浏览器先发送header部分,服务器响应100 continue,浏览器再发送body,服务器响应200(返回数据) GET浏览器主动cache,POST需手动设置 GET参数只能进行 URL 编码,接收 ASCII 字符,POST不限

——————————————————————

HTTP 状态码

1 临时信息 2 成功 3 重定向 4 客户端错误 5** 服务器错误

101 websocket阶段性的确认,收到请求可以继续

200 OK 正常返回信息 202 Accepted 服务器已接受请求,但尚未处理 301 Moved Permanently 请求的网页已永久移动到新位置 302 Found 临时性重定向 304 Not Modified 自从上次请求后,请求的网页未修改过 400 Bad Request 服务器无法理解请求的格式 401 Unauthorized 请求未授权 403 Forbidden 禁止访问 500 Internal Server Error 最常见的服务器端错误 502 Bad Gateway 一般表现为你自己写的应用层服务(Java/Go/PHP)挂了,网关层无法接收到响应 503 Service Unavailable 服务器端暂时无法处理请求 504 Gateway Timeout 一般表现为应用层服务 (upstream) 超时,如查库操作耗时十分钟,超过了 Nginx 配置的超时时间

——————————————————————

请求和响应报文

HTTP request报文 首行:请求方法,请求URI,http协议版本 若干行请求头 请求实体

Host: www.w3.org 
请求的服务器地址

Connection: keep-alive
客户端与服务连接类型

Cache-Control,If-None-Match
https缓存标记

User-Agent: Mozilla/5.0 XXX 
浏览器属性

Referer: https://www.google.com.hk/
发起请求的源地址

Content-Type
客户端希望的得到的内容编码类型
text/html : HTML格式
text/plain :纯文本格式      
text/xml :  XML格式
image/gif :gif图片格式    
image/jpeg :jpg图片格式 
image/png:png图片格式
application/json:JSON数据格式
application/xml: XML数据格式

Accept-Encoding: gzip,deflate,sdch 
客户端支持的数据压缩格式

Cookie: authorstyle=yes  
客户端保存用户信息的一种cookie信息

HTTP response报文结构是怎样的
首行是状态行包括:http协议版本,状态码,状态描述
若干行响应头,包括:通用头部,响应头部,实体头部
响应实体

```ruby
Content-encoding: gzip  
响应数据的压缩格式

Content-length: 1339
响应的内容长度

Content-type: application/javascript
响应数据的内容编码类型

Last-Modified:
响应中的一些标记

Accept-ranges
是否支持断点续传

——————————————————————

fetch是基于Promise,编程式的Web请求方式

fetch('/users', {
  method: 'POST',
  body: {}
})

不能取消

不能获取进度

不能设置超时

兼容性目前比较差

——————————————————————

HTTP/2

HTTP/2 是 HTTP 网络协议的新版本,带来很大的性能提升

1.使用二进制分帧替代文本格式传输,解析效率更高

2.多路复用,允许同时通过单一的TCP连接发起多个的同步请求,解决浏览器连接限制问题

3.利用头部压缩机制减少 请求和响应的实际体积

4.允许服务器主动推送响应

二进制传输 HTTP/2 中引入了新的编码机制,所有传输的数据都会被分割,并采用二进制格式编码

多路复用 帧代表着最小的数据单位,每个帧会标识出该帧属于哪个数据流,以此避免 HTTP 旧版本中的队头阻塞问题,极大的提高传输性能 但是如果出现丢包的情况,整个 TCP 都需要等待重传,会就导致了后面的所有数据都被阻塞

Header 压缩 使用了 HPACK 压缩格式对传输的 header 进行编码,并在两端维护了索引表,以此减少请求头大小

服务端 Push 服务端可以在客户端某个请求后,主动推送其他一定会请求的资源 ——————————————————————

HTTP/3

由于HTTP/2的多路复用出现丢包的情况下,整个TCP都要开始等待重传,阻塞后面的所有请求,所以HTTP/3使用基于UDP 协议的 QUIC 协议解决此问题

1.原生就实现了多路复用,单个数据流可以保证有序交付且不会影响其他的数据流

2.请求报文分数据包和校验包,非校验包丢包的情况时,通过其他包计算出丢失的数据包的内容,避免请求重传

3.使用ID代替IP和端口识别连接,可以迅速重连

——————————————————————

HTTPS

要将网站升级成https,需要后端支持(后端需要申请证书等),然后https的开销也比http要大(因为需要额外建立安全链接以及加密等)

1.客户端发送一个包含随机值的 HTTPS 请求

2.服务端收到请求,自己也产生一个随机值,并且发送自己的 HTTPS 证书

3.客户端收到服务端的证书并验证是否有效,验证通过会再生成一个随机值,通过服务端证书的公钥去加密这个随机值并发送给服务端

4.服务端收到加密过的随机值并使用私钥解密获得第三个随机值,这时候两端都拥有了三个随机值,可以通过这三个随机值按照之前约定的加密方式生成密钥,接下来的通信就可以通过该密钥来进行对称加密的方式通信

对称加密,通信双方使用约定好的固定密钥对传输中的密文进行解密,同一个服务端对多个客户端使用相同的密钥,一旦在与一方的通信中密钥被泄露,其他所有的通信都将被破解

非对称加密 服务端对每个客户端生成一个私钥-公钥对,加密数据使用的是公钥,即便数据被截取,也只能获取公钥和密文,解密密文只能通过客户端才知道的私钥进行解密,且即便一方私钥也被泄露,其他客户端依然不受影响

Https 在内容传输的加密上使用的是对称加密,非对称加密只作用在证书验证阶段,来保证数据传输过程中的加解密效率。当攻击者通过DNS劫持等方式冒充服务端提供公钥并与客户端通信时,可能存在数据泄露的问题,所以我们要在过程中保证证书的合法性

降低被中间人攻击的风险:开启 HSTS,只要第一次访问是安全的,在有效期内就是安全的,一旦出现中间人攻击,浏览器会立即阻止连接, ——————————————————————

WebSocket

WebSocket是针对 http 请求只能由客户端发送到服务端,如果服务器有状态变化只能使用低效率的轮询更新状态的问题,而实现的解决方案

webSocket原理:在TCP连接第一次握手的时候,升级为ws协议。后面的数据交互都复用这个TCP通道。

WebSocket支持双向通信,可以使用二进制传输,支持扩展,无跨域问题

——————————————————————

如何解决跨域问题

同源策略指的是:协议,域名,端口相同

通过jsonp跨域 利用html原生的script标签没有同源限制,来进行跨域请求,但只限于 get 请求所以存在安全问题

跨域资源共享(CORS) CORS 标准定义了一组新的用于跨域请求的请求头,如果服务器设置相关的CORS跨域请求头并实现了相关接口,就可以使用ajax进行跨域请求 // 设置允许其他域名访问 header('Access-Control-Allow-Origin:');
时的一些问题 1.安全性问题 2.由于浏览器SameSite限制不能传cookie,在 HTTPS 协议下才能设置解除SameSite问题 // 设置允许的响应类型 header('Access-Control-Allow-Methods:POST, GET');
// 设置允许的响应头 header('Access-Control-Allow-Headers:x-requested-with,content-type');

Nginx代理跨域 通过同源的请求发送给代码服务器,再由代理服务器解析请求跨域的资源,返回给客户端 可以进行域名转发或者子域名的方式来解决跨域问题

// proxy服务器
server {
    listen       81;
    server_name  www.domain1.com;
    location / {
        proxy_pass   http://www.domain2.com:8080;  #反向代理
        proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
        index  index.html index.htm;

        # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
        add_header Access-Control-Allow-Origin http://www.domain1.com;  #当前端只跨域不带cookie时,可为*
        add_header Access-Control-Allow-Credentials true;
    }
}

Nodejs中间件代理跨域 Node中间件实现跨域代理,原理大致与Nginx相同,都是通过启一个代理服务器,实现数据的转发

——————————————————————

Ajax原理

Ajax的原理简单来说是在用户和服务器之间加了—个中间层(AJAX引擎),利用HTTP异步请求线程进行调度,通过XmlHttpRequest对象来向服务器发送异步请求,获得数据后,用JS来操作DOM更新页面,使用户操作与服务器请求异步化

——————————————————————

负载均衡

用户发起的请求都指向调度服务器(反向代理服务器,譬如安装了nginx控制负载均衡),然后调度服务器根据所用的调度算法,将不同的请求分配给集群中的对应服务器执行,调度器再等待实际服务器的HTTP响应,并反馈给用户

options 请求

对那些可能对服务器数据产生副作用(对服务器端资源做修改)的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。