Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

网络部分常见问题 #29

Open
lznbuild opened this issue Jun 16, 2020 · 0 comments
Open

网络部分常见问题 #29

lznbuild opened this issue Jun 16, 2020 · 0 comments

Comments

@lznbuild
Copy link
Owner

lznbuild commented Jun 16, 2020

http状态码

  • 1XX 临时返回,表示客户端继续其请求,被浏览器HTTP库直接处理掉了,不会让上层应用知道

  • 2XX 请求成功

  • 3XX 表示请求的目标有变化,希望客户端进一步处理

    301&302:永久性与临时性跳转。

    304:跟客户端缓存没有更新。产生这个状态的前提是:客户端本地已经有缓存的版本,并且在 Request 中告诉了服务端,当服务端通过时间或者 tag,发现没有更新的时候,就会返回一个不含 body 的 304 状态

  • 4xx:客户端请求错误。

    403:无权限。

    404:表示请求的资源不存在。

  • 5xx:内部服务器错误

GET POST请求的区别

  • GET 参数通过 url 传递,POST 放在 body 中,POST相对安全

  • GET 请求在 url 中传递的参数是有长度限制的,而 POST 没有,长度限制来源于浏览器对地址栏输入内容的限制,非GET请求本身的限制

  • GET 在浏览器回退时是无害的(有缓存,协商缓存),而 POST 会再次提交请求,也就是说,GET 请求会被浏览器主动 cache,而 POST 不会,除非手动设置。

  • GET 请求只能进行 url(x-www-form-urlencoded)编码,而 POST 支持多种编码方式。

  • GET 产生一个 TCP 数据包;POST 产生两个 TCP 数据包。对于 GET 方式的请求,浏览器会把 http 的 header 和 data 一并发送出去,服务器响应200(返回数据)。而对于 POST,浏览器先发送 header,服务器响应100 continue,浏览器再发送 data,服务器响应200 ok(返回数据)

POST和PUT请求的区别

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

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

http通用头部字段

  • Cache-Control  控制缓存

  • Connection 设置为Keep-alive用于告诉客户端本次HTTP请求结束之后并不需要关闭TCP连接,这样可以使下次HTTP请求使用相同的TCP通道,节省TCP连接建立的时间。

  • Upgrade  升级为其他协议

  • via 代理服务器的相关信息

  • Transfor-Encoding 报文主体的传输编码格式

  • Pragma 报文指令

  • Date 创建报文的日期

HTTP请求头里有那些字段

  • origin:发起请求的服务器地址

  • Accept :客户端或者代理能够处理的媒体类型

  • Accept-Encoding 优先可处理的编码格式

  • Accept-Language 优先可处理的自然语言

  • Accept-Charset 优先可以处理的字符集

  • If-Match 比较实体标记(ETage)

  • If-None-Match 比较实体标记(ETage)与 If-Match相反

  • If-Modified-Since 比较资源更新时间(Last-Modified)

  • Authorization web的认证信息 ✨

  • Host 请求资源所在服务器 ✨

  • User-Agent 客户端程序信息 ✨

  • Referer 请求原始放的url

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: 无连接,不可靠,面向报文,没有阻塞控制,一对一,一对多,多对一,多对多通讯,简单,快速,无队头阻塞的问题

全双工通信

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

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

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

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

  • DNS优化。由于DNS劫持或故障造成的服务不可用,进而影响用户体验。大部分标准DNS都是基于UDP与DNS服务器交互的,HTTPDNS则是利用HTTP协议与DNS服务器交互,绕开了运营商的Local DNS服务,有效防止了域名劫持,提高域名解析效率。简单来说就是DNS解析不通过运营商,通过自己的服务器

  • 升级协议http2.0,多路复用。

  • 数据压缩优化。 传输数据大小的问题。数据对请求速度的影响分两方面,一是压缩率,二是解压序列化反序列化的速度。目前最流行的两种数据格式是 json 和 protobuf,json 是字符串,protobuf 是二进制,即使用各种压缩算法压缩后,protobuf 仍会比 json 小,数据量上 protobuf 有优势,序列化速度 protobuf 也有一些优势

  • PWA做离线缓存

正向代理

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

实例:

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

反向代理

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

实例:

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

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

  • 都是做为服务器和客户端的中间层

  • 都可以加强内网的安全性,阻止 web 攻击

  • 都可以做缓存机制

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant