lznbuild / my-blog

自己的博客
9 stars 1 forks source link

网络部分常见问题 #29

Open lznbuild opened 4 years ago

lznbuild commented 4 years ago

http状态码

GET POST请求的区别

POST和PUT请求的区别

PUT是幂等的,连续调用一次或者多次的效果相同(无副作用), 如果两个请求相同,后一个请求会把第一个请求覆盖掉 (PUT更多的用来改资源)

POST是非幂等的方式,后一个请求不会把第一个请求覆盖掉(POST更多的用来增资源)

http通用头部字段

HTTP请求头里有那些字段

HTTP响应头里有那些字段

Location:令客户端重定向的URI

Last-Modified:该资源最后被修改的时间

set-cookie:设置cookie

content-length

content-type

date ETag

Expires

keep-alive

TCP为什么要三次握手

先大概说一下流程。

第一次握手,客户端发了个连接请求消息到服务端,服务端收到信息后知道自己与客户端是可以连接成功的,但此时客户端并不知道服务端是否已经接收到了它的请求。

第二次握手,服务端接收到消息后的应答,客户端得到服务端的反馈后,才确定自己与服务端是可以连接上的, 客户端只有确定了自己能与服务端连接上才能开始发数据。所以两次握手肯定是最基本的。

第三次握手,是为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误。如果没有第3次,服务器端是不知道客户端有没有接收到服务器端返回的信息,造成服务器端开销的严重浪费。

再归纳一下 每一步。

seq 序列号

ack 确认号,只有ACK为1时,它才有效, ack = seq+1

标志位

ACK: 确认序号有效
SYN: 发起一个新链接
FIN: 释放一个链接

第一次握手,客户端选择一个随机序列号seq(假设为x),并发送一个SYN数据包(1表示开启新连接,0结束连接),其中可能还包括其他TCP标志和选项,客户端将这个数据包给服务器请求连接。

第二次握手, 服务器用一个带有确认应答ACK(1)和同步序列号SYN(1),ack(x+1),seq(假设为y)的数据段,相应客户端,用来通知客户端,服务端已经收到SYN消息并通过了确认。

第三次握手,客户端笑了,说明,client发送给server,server发送给client都可以,但是server不知道这个整体流程走通了没,所以给ACK(1)seq(x+1),ack(y+1)发送握手期间的最后一个数据包,客户端收到数据后,发送数据段确认收到,服务器收到此数据确认无误,开始传送数据

其实第三次握手的时候,是可以携带数据的。但是,第一次、第二次握手不可以携带数据

为什么要有同步序列号。

TCP协议可以是一个全双工通信的,接收方和发起方都可以发送信息,要有一个序列号,表示那些是同一个请求过程中的。序列号也不能从0开始,会混淆的,相对随机生成的,TCP规范中也不允许连接一直是一个半打开的状态。

TCP的4次挥手

1.首先客户端想要释放连接,向服务器端发送一段TCP报文(连接释放报文),FIN=1,seq=x并停止发送数据

2.服务器端接收到从客户端发出的TCP报文之后,确认了客户端想要释放连接,随后服务器端进入一个半关闭的状态(不能一直持续),并返回一段TCP报文(确认报文) ACK=1,ack=x+1,seq=v

3.服务器端准备好后,再次向客户端发出一段TCP报文 FIN =1,ACK=1, seq=w, ack=x+1 关闭。

4.客户端收到从服务器端发出的TCP报文,确认了服务器端已做好释放连接的准备,再次传输一段报文 ACK=1,ack=w+1,seq=x+1

因为TCP是全双工通信,在关闭连接的时候,既要关闭客户端的连接,也要关掉服务端建立的连接,所以需要四次挥手

为什么建立连接只通信了三次,而断开连接却用了四次?

因为当服务端收到客户端的 FIN 报文后,发送的 ACK 报文只是用来应答的,并不表示服务端也希望立即关闭连接。

当只有服务端把所有的报文都发送完了,才会发送 FIN 报文,告诉客户端可以断开连接了,因此在断开连接时需要四次挥手。

TCP建立连接时之所以只需要"三次握手",是因为在第二次"握手"过程中,服务器端发送给客户端的TCP报文是以SYN与ACK作为标志位的。SYN是请求连接标志,表示服务器端同意建立连接;ACK是确认报文,表示告诉客户端,服务器端收到了它的请求报文。

即SYN建立连接报文与ACK确认接收报文是在同一次"握手"当中传输的,所以"三次握手"不多也不少,正好让双方明确彼此信息互通。

TCP释放连接时之所以需要“四次挥手”,是因为FIN释放连接报文与ACK确认接收报文是分别由第二次和第三次"握手"传输的。为何建立连接时一起传输,释放连接时却要分开传输?

建立连接时,被动方服务器端结束CLOSED阶段进入“握手”阶段并不需要任何准备,可以直接返回SYN和ACK报文,开始建立连接。 释放连接时,被动方服务器,突然收到主动方客户端释放连接的请求时并不能立即释放连接,因为还有必要的数据需要处理,所以服务器先返回ACK确认收到报文,经过CLOSE-WAIT阶段准备好释放连接之后,才能返回FIN释放连接报文。

所以是“三次握手”,“四次挥手”。

DNS缓存查询过程

搜索浏览器自身的DNS缓存==> 操作系统的hosts文件==> 查找本地DNS服务器 ==> 根服务器 ==> 顶级服务器

options请求

用于获取目的资源所支持的通信选项。 响应报文包含一个 Allow 首部字段,该字段的值表明了服务器支持的所有 HTTP 方法

在 CORS 中,可以使用 OPTIONS 方法发起一个预检请求,以检测实际请求是否可以被服务器所接受。预检请求报文中的 Access-Control-Request-Method 首部字段告知服务器实际请求所使用的 HTTP 方法;Access-Control-Request-Headers 首部字段告知服务器实际请求所携带的自定义首部字段。服务器基于从预检请求获得的信息来判断,是否接受接下来的实际请求。

HTTP1.0 HTTP1.1 HTTP2.0 的区别

  1. HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法。HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法

  2. HTTP1.1中新增了很多错误状态响应码

  3. HTTP 1.1支持长连接。

    在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。通过设置http的请求头部和应答头部,保证本次数据请求结束之后,下一次请求仍可以重用这一通道,避免重新握手。原理是请求完成后不立即释放连接,而是放入连接池中,若这时有另一个请求要发出,请求的域名和端口是一样的,就直接拿出连接池中的连接进行发送和接收数据,少了建立连接的耗时。但有个问题,就是这个 keep-alive 的连接一次只能发送接收一个请求,在上一个请求处理完成之前,无法接受新的请求。

    若同时发起多个请求,就有两种情况:若串行发送请求,可以一直复用一个连接,但速度很慢,每个请求都要等待上个请求完成再进行发送。

    若并行发送这些请求,那么首次每个请求都要进行tcp三次握手建立新的连接,虽然第二次可以复用连接池里这堆连接,但若连接池里保持的连接过多,对服务端资源产生较大浪费,若限制了保持的连接数,并行请求里超出的连接仍每次要建连。

    对这个问题,新一代协议 HTTP2 提出了多路复用去解决。

  4. HTTP/2 采用二进制格式传输数据,解析更高效

  5. 多路复用,支持 TCP 连接复用

  6. 加密。

    HTTPS 有两个作用,一是确定请求的目标服务端身份,二是保证传输的数据不会被网络中间节点窃听或者篡改。HTTPS 是使用加密通道来传输 HTTP 的内容。但是 HTTPS 首先与服务端建立一条 TLS 加密通道。TLS 构建于 TCP 协议之上,它实际上是对传输的内容做一次加密,所以从传输内容上看,HTTPS 跟 HTTP 没有任何区别。

  7. HTTP2.0 支持服务端推送

    服务端推送能够在客户端发送第一个请求到服务端时,提前把一部分内容推送给客户端,放入缓存当中,这可以避免客户端请求顺序带来的并行度不高,从而导致的性能问题。 服务端推送能把客户端所需要的资源伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度。例如我的网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了。

    TCP 连接复用,则使用同一个 TCP 连接来传输多个 HTTP 请求,避免了 TCP 连接建立时的三次握手开销,和初建 TCP 连接时传输窗口小的问题。

http1.1 中的长链接复用和HTTP2.0中的多路复用的区别

在HTTP/1.1协议中,浏览器客户端在同一时间,针对同一域名下的请求有一定数量限制,超过限制数目的请求会被阻塞。(6个)所谓请求阻塞意思就是一条TCP的connection在同一时间只能允许一个请求经过,这样假如后续请求想要复用这个链接就必须等到前一个完成才行

HTTP/2多个请求可同时在一个连接上并行执行。某个请求任务耗时严重,不会影响到其它连接的正常执行,server端可以根据stream的唯一标识来相应对应的请求。HTTP2 的多路复用看起来是完美的解决方案,但还有个问题,就是队头阻塞,这是受限于 TCP 协议,TCP 协议为了保证数据的可靠性,若传输过程中一个 TCP 包丢失,会等待这个包重传后,才会处理后续的包。HTTP2的多路复用让所有请求都在同一条连接进行,中间有一个包丢失,就会阻塞等待重传,所有请求也就被阻塞了。这个问题无法解决,本身http协议就是基于TCP协议

HTTP的长连接有什么特点

http header中有个connection属性,close是短链接,connection:keep-alive是长连接,通过这个字段区分长连接和短链接。

优点:

1.减少TCP的握手次数

2.减少慢启动的影响 TCP可以发送很大的资源,100MB以上的这种,但网络带宽是有限的,所以就有一个优化机制,TCP连接都有一个由慢到快的过程,避免一下把带宽占满。

缺点:

tcp也是一种字符流的协议,传输一个文件,要从文件开头传到结尾,一个字节一个字节的传输,顺序不能乱,而且是串行的,会有队头阻塞问题

TCP比较可靠?

TCP 之所以可靠,大体上由于以下原因:

数据包校验:目的是检测数据在传输过程中的任何变化,若校验出包有错,则丢弃报文段并且不给出响应,这时 TCP 发送数据端超时后会重发数据;

对失序数据包重排序:既然 TCP 报文段作为 IP 数据报来传输,而 IP 数据报的到达可能会失序,因此 TCP 报文段的到达也可能会失序。TCP 将对失序数据进行重新排序,然后才交给应用层;

丢弃重复数据:对于重复数据,能够丢弃重复数据;

应答机制:当 TCP 收到发自 TCP 连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒;

超时重发:当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段;

流量控制:TCP 连接的每一方都有固定大小的缓冲空间。TCP 的接收端只允许另一端发送接收端缓冲区所能接纳的数据,这可以防止较快主机致使较慢主机的缓冲区溢出,这就是流量控制。

TCP和UDP协议的区别

TCP : 可靠(重发机制),传递任意长度消息(字符流协议) 分包通过序列号组合, 阻塞控制 ,需要建立连接,每一条TCP连接只能是1对1,提供全双工通信

UDP: 无连接,不可靠,面向报文,没有阻塞控制,一对一,一对多,多对一,多对多通讯,简单,快速,无队头阻塞的问题

全双工通信

单工数据传输只支持数据在一个方向上传输(电视)

半双工数据传输允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;(对讲机)

全双工数据通信允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。(手机微信)

弱网环境下的前端优化手段有哪些

正向代理

代理客户。需要主动设置代理服务器IP或者域名进行访问,由正向代理服务器去获取访问内容并返回。相当于中间人借钱,有钱人(服务器)只知道中间人(正向代理服务器)是谁,不知道真正借钱的人(客户端)是谁。隐藏真实的客户,为客户端收发请求,使真实客户端对服务器不可见。

实例:

一个局域网内的所有用户可能被一台服务器做了正向代理,由该台服务器负责 HTTP 请求,意味着同服务器做通信的是正向代理服务器;

反向代理

代理服务器。不需要客户端做任何设置,反向代理服务器会根据访问内容进行跳转及内容返回,你不知道它最终访问的是哪些机器。隐藏了真实的服务器,为服务器收发请求,使真实服务器对客户端不可见。相当于120电话,打120后不知道哪家医院的救护车会来。

实例:

负载均衡服务器,将用户的请求分发到空闲的服务器上; 意味着用户和负载均衡服务器直接通信,即用户解析服务器域名时得到的是负载均衡服务器的 IP。

正向代理和反向代理的共同点

TCP的粘包问题

默认情况下, TCP 连接会启⽤延迟传送算法 (Nagle 算法), 在数据发送之前缓存他们. 如果短时间有多个数据发送, 会缓冲到⼀起作⼀次发送 (缓冲⼤⼩⻅ socket.bufferSize ), 这样可以减少 IO 消耗提⾼性能.

如果是传输⽂件的话, 那么根本不⽤处理粘包的问题, 来⼀个包拼⼀个包就好了. 但是如果是多条消息, 或者是别的⽤途的数据那么就需要处理粘包.

HTTP2.0

多路复用
支持传输2进制数据类型
服务器端主动推送
header压缩

HTTP3.0

当然 HTTP/2 也并非完美,考虑一种情况,如果客户端或服务端在通信时出现数据包丢失,或者任何一方的网络出现中断,那么整个 TCP 连接就会暂停。

HTTP/2 由于采用二进制分帧进行多路复用,通常只使用一个 TCP 连接进行传输,在丢包或网络中断的情况下后面的所有数据都被阻塞。但对于 HTTP/1.1 来说,可以开启多个 TCP 连接,任何一个 TCP 出现问题都不会影响其他 TCP 连接,剩余的 TCP 连接还可以正常传输数据。这种情况下 HTTP/2 的表现就不如 HTTP/1 了。

2018 年 HTTP/3 将底层依赖的 TCP 改成 UDP,从而彻底解决了这个问题。UDP 相对于 TCP 而言最大的特点是传输数据时不需要建立连接,可以同时发送多个数据包,所以传输效率很高,缺点就是没有确认机制来保证对方一定能收到数据。

建立一个TCP连接后,是否会在一个HTTP请求完成断开?

http1.0会,http1.1支持长链接,connection: keep-alive,维持TCP连接,SSL的开销也可以避免。

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Overview
https://www.cnblogs.com/chenqf/p/6386163.html https://juejin.im/post/5c7a9f8c518825640d1dd503#heading-16