计算机网络

HTTP

Http请求的完整过程

流览器中的HTTP请求从发起到结束一共经历了如下八个阶段:构建请求、查找缓存、准备IP和端口、等待TCP队列、建立TCP连接、发起HTTP请求、服务器处理请求、服务器返回请求和断开连接。

http的methods有哪些?

可以参考methods中列出的一些。 'get', 'post', 'put', 'head', 'delete', 'options', 'trace', 'copy', 'lock', 'mkcol', 'move', 'purge', 'propfind', 'proppatch', 'unlock', 'report', 'mkactivity', 'checkout', 'merge', 'm-search', 'notify', 'subscribe', 'unsubscribe', 'patch', 'search', 'connect'

http有哪些常用的head,说一下各自的作用?

Expires

HTTP1.0的内容,服务器使用Expires头来告诉Web客户端它可以使用当前副本,直到指定的时间为止

Cache-Control

HTTP1.1引入了Cathe-Control,它使用max-age指定资源被缓存多久,主要是解决了Expires一个重大的缺陷,就是它设置的是一个固定的时间点,客户端时间和服务端时间可能有误差。

所以一般会把两个头都带上,这种缓存称为强缓存,表现形式为:

Last-Modified / If-Modified-Since

Last-Modified是服务器告诉浏览器该资源的最后修改时间,If-Modified-Since是请求头带上的,上次服务器给自己的该资源的最后修改时间。然后服务器拿去对比。

若资源的最后修改时间大于If-Modified-Since,说明资源又被改动过,则响应整片资源内容,返回状态码200;

若资源的最后修改时间小于或等于If-Modified-Since,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用当前版本。

Etag / If-None-Match

前面提到由文件的修改时间来判断文件是否改动,还是会带来一定的误差,比如注释等无关紧要的修改等。所以推出了新的方式。

Etag是由服务端特定算法生成的该文件的唯一标识,而请求头把返回的Etag值通过If-None-Match再带给服务端,服务端通过比对从而决定是否响应新内容。这也是304缓存,也称为协商缓存。

说明下Etag是怎么生成的?

nginx里面,是由Last-Modified和content-length的十六进制组合而成 不同 Web 服务器或者 CDN 的 ETag 生成方式不一样。

开发中常用的几种 Content-Type?

(1)application/x-www-form-urlencoded

浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。该种方式提交的数据放在 body 数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。

(2)multipart/form-data

该种方式也是一个常见的 POST 提交方式,通常表单上传文件时使用该种方式。

(3)application/json

告诉服务器消息主体是序列化后的 JSON 字符串。

(4)text/xml

该种方式主要用来提交 XML 格式的数据。

参考:

常用的几种 Content-Type | 独 奏

Keep-alive如何开启?有什么用?原理是什么?

在 HTTP 1.0 中, 没有官方的 keepalive 的操作。通常是在现有协议上添加一个指数。如果浏览器支持 keep-alive,它会在请求的包头中添加: Connection: Keep-Alive 然后当服务器收到请求,作出回应的时候,它也添加一个头在响应中: Connection: Keep-Alive。 这样做,连接就不会中断,而是保持连接。当客户端发送另一个请求时,它会使用同一个连接。这一直继续到客户端或服务器端认为会话已经结束,其中一方中断连接。

HTTP 1.1 中 所有的连接默认都是持续连接,除非特殊声明不支持。

介绍下 http1.0、1.1、2.0 协议的区别?

参考

HTTP/2引入了“服务端推(server push)”的概念,它允许服务端在客户端需要数据之前就主动地将数据发送到客户端缓存中,从而提高性能。

HTTP/2提供更多的加密支持

HTTP/2使用多路技术,允许多个消息在一个连接上同时交差。

它增加了头压缩(header compression),因此即使非常小的请求,其请求和响应的header都只会占用很小比例的带宽。

http1.1协议的缺点

HTTP/1.1 默认使用了持久连接,多个请求可以复用同一个 TCP 连接,但是在同一个 TCP 连接里面,数据请求的通信次序 是固定的。服务器只有处理完一个请求的响应后,才会进行下一个请求的处理,如果前面请求的响应特别慢的话,就会造成许 多请求排队等待的情况,这种情况被称为“队头堵塞”。

队头阻塞会导致持久连接在达到最大数量时,剩余的资源需要等待其他 资源请求完成后才 能发起请求。

为了避免这个问题,一个是减少请求数,一个是同时打开多个持久连接。这就是 我们对网站优化时,使用雪碧图、合并脚本的 原因。

http2有哪些特性?

多路复用、首部压缩、服务器推送

http2多路复用是什么?解决了什么问题?

在 HTTP/1 中,每次请求都会建立一次HTTP连接,也就是我们常说的3次握手4次挥手,这个过程在一次请求过程中占用了相当长的时间,即使开启了 Keep-Alive ,解决了多次连接的问题,但是依然有两个效率上的问题:

第一个:串行的文件传输。当请求a文件时,b文件只能等待,等待a连接到服务器、服务器处理文件、服务器返回文件,这三个步骤。我们假设这三步用时都是1秒,那么a文件用时为3秒,b文件传输完成用时为6秒,依此类推。(注:此项计算有一个前提条件,就是浏览器和服务器是单通道传输)

第二个:连接数过多。我们假设Apache设置了最大并发数为300,因为浏览器限制,浏览器发起的最大请求数为6,也就是服务器能承载的最高并发为50,当第51个人访问时,就需要等待前面某个请求处理完成。

HTTP/2的多路复用就是为了解决上述的两个性能问题。

在 HTTP/2 中,有两个非常重要的概念,分别是帧(frame)和流(stream)。而http1是基于文本的,没有流的概念,所以无法实现多路复用

帧代表着最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流。

多路复用,就是在一个 TCP 连接中可以存在多条流。换句话说,也就是可以发送多个请求,对端可以通过帧中的标识知道属于哪个请求。通过这个技术,可以避免 HTTP 旧版本中的队头阻塞问题,极大的提高传输性能。

http2的首部压缩什么原理?

因为每个HTTP 报文都要传输臃肿的首部字段导致的网络效率降低,解决思路,通信双方可以都维护一张HTTP 首部字段索引列表,报文中只传输对应字段的索引值,就能大大压缩报文首部的长度,提高网络利用率。HTTP/2 在客户端与服务器端都维护了一张首部字段索引列表, header 字段列表是以key - value 键值对元素构成的有序集合,每个header 字段元素都映射为一个索引值,报文中使用header 字段的索引值进行二进制编码传输,显然比HTTP/1.1 直接使用header 字段ASCII 编码传输,数据量小得多,这种减少header 字段传输开销的技术可以称为首部压缩HPACK。

http2的服务器推送是什么,如何实现?

服务器推送(server push)指的是,还没有收到浏览器的请求,服务器就把各种资源推送给浏览器。

比如,浏览器只请求了index.html,但是服务器把index.html、style.css、example.png全部发送给浏览器。这样的话,只需要一轮 HTTP 通信,浏览器就得到了全部资源,提高了性能。

服务器推送(server push)是 HTTP/2 协议里面,唯一一个需要开发者自己配置的功能。其他功能都是服务器和浏览器自动实现,不需要开发者关心。

实现主要通过修改nginx配置来完成,或者服务器推送还有另一个实现方法,就是后端应用产生 HTTP 回应的头信息Link命令。

参考:

HTTP/2 服务器推送(Server Push)教程 - 阮一峰的网络日志

介绍下http3

随着网络技术的发展,1999 年设计的 HTTP/1.1 已经不能满足需求,所以 Google 在 2009 年设计了基于 TCP 的 SPDY,后来 SPDY 的开发组推动 SPDY 成为正式标准,不过最终没能通过。不过 SPDY 的开发组全程参与了 HTTP/2 的制定过程,参考了 SPDY 的很多设计,所以我们一般认为 SPDY 就是 HTTP/2 的前身。无论 SPDY 还是 HTTP/2,都是基于 TCP 的,TCP 与 UDP 相比效率上存在天然的劣势,所以 2013 年 Google 开发了基于 UDP 的名为 QUIC 的传输层协议,QUIC 全称 Quick UDP Internet Connections,希望它能替代 TCP,使得网页传输更加高效。后经提议,互联网工程任务组正式将基于 QUIC 协议的 HTTP (HTTP over QUIC)重命名为 HTTP/3。

QUIC和http3的区别?

QUIC 是用来替代 TCP、SSL/TLS 的传输层协议,在传输层之上还有应用层,我们熟知的应用层协议有 HTTP、FTP、IMAP 等,这些协议理论上都可以运行在 QUIC 之上,其中运行在 QUIC 之上的 HTTP 协议被称为 HTTP/3,这就是”HTTP over QUIC 即 HTTP/3“的含义。

QUIC基于UDP怎么保证可靠性?

QUIC改进了TCP的拥塞控制。

对于流量控制:

QUIC 的流量控制和 TCP 有点区别,TCP 为了保证可靠性,窗口左边沿向右滑动时的长度取决于已经确认的字节数。如果中间出现丢包,就算接收到了更大序号的 Segment,窗口也无法超过这个序列号。

但 QUIC 不同,就算此前有些 packet 没有接收到,它的滑动只取决于接收到的最大偏移字节数。

QUIC 一个连接上的多个 stream 之间没有依赖。这样假如 stream2 丢了一个 udp packet,也只会影响 stream2 的处理。不会影响 stream2 之前及之后的 stream 的处理。

参考:

QUIC

QUIC可靠性

简单介绍下https

HTTPS 指的是超文本传输安全协议,HTTPS 是基于 HTTP 协议的,不过它会使 用 TLS/SSL 来对数据加密。

使用 TLS/ SSL 协议,所有的信息都是加密的,第三方没有办法窃听。并且它提供了一种校验机制,信息一旦被篡改,通信的双方 会立 刻发现。它还配备了身份证书,防止身份被冒充的情况出现。

https的握手过程是什么样子的?

开始加密通信之前,客户端和服务端必须建立连接和交互参数,这个过程就是握手。

第一步:客户端 say hello, 向服务端发送自己生成的 random 数,和自己支持的加密方法。

第二步:服务端接收消息后,又向客户端发送自己生成的 random 数、SSL 证书,确定使用的加密方法。

第三步:客户端读取证书信息,如果证书无效,则提示告警;如果证书有效,然后自己再生成一个 random 数,并使用证书的公钥进行加密,发送给服务端。

第四步:服务端使用自己本地的私钥,解密获取客户端的随机数。

第五步:客户端和服务端使用这三个随机数生成对话密钥, 用来加密接下来的对话过程,并通知客户端后面的数据段会加密传输。

如果每次建立连接都去进行这五步,那么会很浪费时间。 所以这里有 sessionID 和 session ticket 两种。

session ID,记录有本次的握手存在,再次发送信息时,客户端发送该ID,服务器确认该编号存在,双方就不再进行握手阶段剩余的步骤,而直接用已有的对话密钥进行加密通信。

但是它的缺点在于session ID往往只保留在一台服务器上。所以,如果客户端的请求发到另一台服务器,就无法恢复对话。session ticket就是为了解决这个问题而诞生的,目前只有Firefox和Chrome浏览器支持。session ticket是加密的,只有服务器才能解密,其中包括本次对话的主要信息,比如对话密钥和加密方法。当服务器收到session ticket以后,解密后就不必重新生成对话密钥了。

当客户端想要通过 HTTPS 请求访问服务端时,整个过程需要经过 7 次握手并消耗 9 倍的延迟:

1、TCP 协议需要通过三次握手建立 TCP 连接保证通信的可靠性(1.5-RTT);

2、TLS 协议会在 TCP 协议之上通过四次握手建立 TLS 连接保证通信的安全性(2-RTT);

3、HTTP 协议会在 TCP 和 TLS 上通过一次往返发送请求并接收响应(1-RTT);

需要注意的是,本文对往返延时的计算都基于特定的场景以及特定的协议版本,网络协议的版本在不断更新和演进,过去忽略的问题最开始都会通过补丁的方式更新,但是最后仍然会需要从底层完成重写。

HTTP/3 就是一个这样的例子,它会使用基于 UDP 的 QUIC 协议进行握手,将 TCP 和 TLS 的握手过程结合起来,把 7 次握手减少到了 3 次握手,直接建立了可靠并且安全的传输通道,将原本 ~900ms 的耗时降低至 ~500ms

参考:

配置SSL,方法及须知原理

为什么 HTTPS 需要 7 次握手以及 9 倍时延 - 面向信仰编程

https是对称还是非对称加密?

https过程中,非对称加密和对称加密是都有的。

首先了解非对称加密、对称加密和单向散列加密的区别?

非对称加密的加解密效率是非常低的,而 http 的应用场景中通常端与端之间存在大量的交互,非对称加密的效率是无法接受的;

另外,在 HTTPS 的场景中只有服务端保存了私钥,一对公私钥只能实现单向的加解密,所以 HTTPS 中内容传输加密采取的是对称加密,而不是非对称加密。HTTPS在证书验证的时候会采用非对称加密



参考:

HTTPS就安全了吗?会被抓包吗?看完这篇你有对答如流

为什么需要 CA 认证机构颁发证书?

首先了解https中间人攻击是什么?如何防护?,如果不是CA认证,就会出现中间人攻击的问题。

参考:

HTTPS就安全了吗?会被抓包吗?看完这篇你有对答如流

浏览器如何验证证书的合法性?

浏览器发起 HTTPS 请求时,服务器会返回网站的 SSL 证书,浏览器需要对证书做以下验证:

1、验证域名、有效期等信息是否正确。证书上都有包含这些信息,比较容易完成验证;

2、判断证书来源是否合法。每份签发证书都可以根据验证链查找到对应的根证书,操作系统、浏览器会在本地存储权威机构的根证书,利用本地根证书可以对对应机构签发证书完成来源验证;

3、判断证书是否被篡改。需要与 CA 服务器进行校验;

4、判断证书是否已吊销。通过CRL(Certificate Revocation List 证书注销列表)和 OCSP(Online Certificate Status Protocol 在线证书状态协议)实现,其中 OCSP 可用于第3步中以减少与 CA 服务器的交互,提高验证效率

以上任意一步都满足的情况下浏览器才认为证书是合法的。

参考:

HTTPS就安全了吗?会被抓包吗?看完这篇你有对答如流

想办法在https的网站下进行http的请求?

<script> 均默认阻止
XMLHttpRequest 阻止
<a> 不会产生混合内容
<img> 仍会加载混合内容图像,但也会向用户显示警告

或者加上

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />

如果登陆的请求是https,而其它的请求是http的会出现什么问题?

cookie会加密,可能导致其它请求无法通过身份验证。

https用哪些端口?

443端口用来验证服务器端和客户端的身份,比如验证证书的合法性

80端口用来传输数据(在验证身份合法的情况下,用来数据传输)

参考:

Node.js 有难度的面试题,你能答对几个? - 云+社区 - 腾讯云

get和post有什么区别?越底层越好。

  • GET在浏览器回退时是无害的,而POST会再次提交请求。

  • GET产生的URL地址可以被Bookmark,而POST不可以。

  • GET请求会被浏览器主动cache,而POST不会,除非手动设置。

  • GET请求只能进行url编码,而POST支持多种编码方式。

  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。

  • GET请求在URL中传送的参数是有长度限制的,而POST么有。

  • 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。

  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。

  • GET参数通过URL传递,POST放在Request body中。

  • GET产生一个TCP数据包;POST产生两个TCP数据包

对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);

而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

当然每个浏览器实现不一致,但是这是标准规范。

参考:

99%的人理解错 HTTP 中 GET 与 POST 的区别 - OSCHINA

http状态码之304

参考http有哪些常用的head,说一下各自的作用?中的304缓存来说。

301重定向和302重定向的区别

301重定向是永久的重定向,搜索引擎在抓取新的内容的同时也将旧的网址替换为了重定向之后的网址

302重定向只是暂时的重定向,搜索引擎会抓取新的内容而保留旧的地址

301请求是可以缓存的, 即通过看status code,可以发现后面写着from cache。

参考:

状态码301和302的区别 - Wayne-Zhu - 博客园

如果作为短链服务的重定向,选301还是302?

301 是永久重定向,302 是临时重定向。短地址一经生成就不会变化,所以用 301 是符合 http 语义的,浏览器会记录跳转地址,同时对服务器压力也会有一定减少。

但是如果使用了 301,我们就无法统计到短地址被点击的次数了,如果对数据统计有要求的话,使用302跳转可能比较好一些!

http请求中的OPTIONS是做什么的?

OPTIONS 请求与 HEAD 类似,一般也是用于客户端查看服务器的性能。这个方法会请求服务 器返回该资源所支持的所有 HTTP 请求方法,该方法会用'*'来代替资源名称,向服务器发送 OPTIONS 请求,可以测试服务器功能 是否正常。

JS 的 XMLHttpRequest对象进行 CORS 跨域资源共享时,对于复杂请求,就是使用 OPTIONS 方法发送嗅探请求,以 判断是否有对指定资源的访问权限。具体可以参考cors情况下,简单请求和复杂请求有什么区别?

gzip有几个压缩级别?

gzip压缩级别仅确定1-9范围内数据的压缩程度,其中9压缩率最高。折衷方案是,压缩率最高的数据通常需要最多的工作来进行压缩/解压缩,因此,如果在高流量的网站上将其设置得很高,则可能会感觉到其效果。

听起来您的问题与请求上的HTTP标头更相关。通常,Content-Encoding: gzip标头会伴随gzip压缩的HTTP流量。

跨域

什么是同源策略

同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源

同源策略的限制内容

同源策略限制内容有:

  • Cookie、LocalStorage、IndexedDB 等存储性内容
  • DOM 节点
  • AJAX 请求不能发送

但是有三个标签是允许跨域加载资源:

  • <img src=XXX>
  • <link href=XXX>
  • <script src=XXX>

特别说明两点:
第一:如果是协议和端口造成的跨域问题“前台”是无能为力的。
第二:在跨域问题上,仅仅是通过“URL的首部”来识别而不会根据域名对应的IP地址是否相同来判断。“URL的首部”可以理解为“协议, 域名和端口必须匹配”。

请求跨域了,那么请求到底发出去没有?
跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。

跨域解决方案

jsonp

JSONP原理: 利用<script> 标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以。

优点:JSONP优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。

缺点:缺点是仅支持get方法具有局限性,不安全可能会遭受XSS攻击。

CORS跨域如何实现?

服务端设置 Access-Control-Allow-Origin 就可以开启 CORS

CORS情况下,简单请求和复杂请求有什么区别?

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

服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。

所以说复杂请求会多一次option的通信。

若请求满足所有下述条件,则该请求可视为“简单请求”:

  • 使用下列方法之一:
    • GET
    • HEAD
    • POST
  • 除了被用户代理自动设置的首部字段(例如 Connection ,User-Agent)和在 Fetch 规范中定义为 禁用首部名称 的其他首部,允许人为设置的字段为 Fetch 规范定义的 对 CORS 安全的首部字段集合。该集合为:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (需要注意额外的限制)
    • DPR
    • Downlink
    • Save-Data
    • Viewport-Width
    • Width
  • Content-Type 的值仅限于下列三者之一:
    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded
  • 请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。
  • 请求中没有使用 ReadableStream 对象。

参考:

HTTP访问控制(CORS) - HTTP | MDN

postMessage

postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:

  • 页面和其打开的新窗口的数据传递
  • 多窗口之间消息传递
  • 页面与嵌套的iframe消息传递
  • 上面三个场景的跨域数据传递

nginx反向代理

通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录

正向代理和反向代理

正向代理:用户知道目标服务器地址,但由于网络限制等原因,无法直接访问。这时候需要先连接代理服务器,然后再由代理服务器访问目标服务器。

反向代理对用户则是不可知的,比如我们访问网站,具体内部的服务器节点我们不知道,现实中我们通过访问代理服务器后,代理服务器给我们转发请求到他们N多的服务器节点中的一个给我们进行搜索后将结果返回。

参考

TCP

简单介绍下TCP协议

TCP 协议是面向连接的,提供可靠数据传输服务的传输层协议。

TCP 协议是面向连接的,在通信双方进行通信前,需要通过三次握手建 立连接。它需要在端系统中维护双方连接的状态信息。

TCP 协议通过序号、确认号、定时重传、检验和等机制,来提供可靠的 数据传输服务。

TCP 协议提供的是点对点的服务,即它是在单个发送方和单个接收方之 间的连接。

TCP 协议提供的是全双工的服务,也就是说连接的双方的能够向对方发 送和接收数据。

TCP 提供了拥塞控制机制,在网络拥塞的时候会控制发送数据的速率, 有助于减少数据包的丢失和减轻网络中的拥塞程度。

TCP 提供了流量控制机制,保证了通信双方的发送和接收速率相同。如果接收方可接收的缓存很小时,发送方会降低发送 速率,避免因为缓存 填满而造成的数据包的丢失。

如何理解三次握手和四次挥手?

一张图片解决问题:

首先,建立连接阶段。这个阶段是通过“三次握手”来建立客戶端和服务器之间的连接。TCP 提供面向连 接的通信传输。面向连接是指在数据通信开始之前先做好两端之间的准备工作。所谓三次握手,是指在建 立一个TCP连接时,客戶端和服务器总共要发送三个数据包以确认连接的建立。

其次,传输数据阶段。在该阶段,接收端需要对每个数据包进行确认操作,也就是接收端在接收到数据包 之后,需要发送确认数据包给发送端。所以当发送端发送了一个数据包之后,在规定时间内没有接收到接 收端反馈的确认消息,则判断为数据包丢失,并触发发送端的重发机制。同样,一个大的文件在传输过程 中会被拆分成很多小的数据包,这些数据包到达接收端后,接收端会按照TCP头中的序号为其排序,从而 保证组成完整的数据。

最后,断开连接阶段。数据传输完毕之后,就要终止连接了,涉及到最后一个阶段“四次挥手”来保证双 方都能断开连接。

TCP为什么要三次握手?

TCP 建立连接时通过三次握手可以有效地避免历史错误连接的建立,减少通信双方不必要的资源消耗,三次握手能够帮助通信双方获取初始化序列号,它们能够保证数据包传输的不重不丢,还能保证它们的传输顺序,不会因为网络传输的问题发生混乱,到这里不使用『两次握手』和『四次握手』的原因已经非常清楚了:

  • 『两次握手』:无法避免历史错误连接的初始化,浪费接收方的资源;
  • 『四次握手』:TCP 协议的设计可以让我们同时传递 ACK 和 SYN 两个控制信息,减少了通信次数,所以不需要使用更多的通信次数传输相同的信息;

参考:

为什么 TCP 建立连接需要三次握手 - 面向信仰编程

TCP四次挥手的原因是?

四次挥手,首先客户端向服务端发送一个FIN包,进入FIN_WAIT1状态,服务端收到后,向客户端发送ACK确认包,进入CLOSE_WAIT状态,然后客户端收到ACK包后进入FIN_WAIT2状态,然后服务端再把自己剩余没传完的数据发送给客户端,发送完毕后在发送一个FIN+ACK包,进入LAST_ACK(最后确认)状态,客户端收到FIN+ACK包后,再向服务端发送ACK包,在等待两个周期后在关闭连接

之所以等待两个周期是因为最后服务端发送的ACK包可能会丢失,如果不等待2个周期的话,服务端在没收收到ACK包之前,会不停的重复发送FIN包而不关闭,所以得等待两个周期

TCP为什么可靠?

TCP的可靠是针对UDP不可靠而言的。

首先了解UDP:

IP通过IP地址信息把数据包发送给指定 的电脑,而UDP通过端口号把数据包分发给正确的程序。

和IP头一样,端口号会被装进UDP头里面,UDP头 再和原始数据包合并组成新的UDP数据包。

UDP头中除了目的端口,还有源端口号等信息。

在使用UDP发送数据时,有各种因素会导致数据包出错,虽然UDP可以校验数据是否正确,但是对于错误的数据包,UDP并不提供重发机制,只是丢弃当前的包,而且UDP在发送之后也无法知道是否能达到目的地。所以说UDP不可靠

TCP(Transmission Control Protocol,传输控制协议)是一种面向 连接的、可靠的、基于字节流的传输层通信协议。相对于UDP,TCP有下面两个特点:

  • 对于数据包丢失的情况,TCP提供重传机制;

  • TCP引入了数据包排序机制,用来保证把乱序的数据包组合成一个完整的文件。

TCP单个数据包的传输流程和UDP流程差不 多,不同的地方在于,通过TCP头的信息保证了一块大的数据传输的完整性

既然TCP可靠,UDP不可靠,那为什么有那么多基于UDP的协议呢?

因为 upd 报文小,udp 头部8个字节,tcp 头部20个字节。,TCP为了保证数据传输的可靠性,牺牲了数据包的传输速度,因为“三次握 手”和“数据包校验机制”等把传输过程中的数据包的数量提高了一倍。

虽说UDP不能保证数据可靠性,但是传输速度却非常快,所以UDP会应用在一些关注速度、但不那么严格要求数据完整性的领域,如在线视频、互动游戏

可以参考一个包大小对比图:

TCP的性能问题,究竟在哪里?

  • TCP 的拥塞控制在发生丢包时会进行退让,减少能够发送的数据段数量,但是丢包并不一定意味着网络拥塞,更多的可能是网络状况较差;
  • TCP 的三次握手带来了额外开销,这些开销不只包括需要传输更多的数据,还增加了首次传输数据的网络延迟;
  • TCP 的重传机制在数据包丢失时可能会重新传输已经成功接收的数据段,造成带宽的浪费;

为了解决 TCP 的性能问题,目前业界有两种解决方案:

  • 使用 UDP 构建性能更加优异、更灵活的传输协议,例如:QUIC19 等;
  • 通过不同的手段优化 TCP 协议的性能,例如:选择性 ACK(Selective ACK, SACK),TCP 快开启(TCP Fast Open, TFO);

由于 TCP 协议在操作系统内核中,不利于协议的更新,所以第一种方案目前发展的更好,HTTP/3 就使用了 QUIC 作为传输协议20。

参考:

为什么 TCP 协议有性能问题 - 面向信仰编程

现代浏览器在与服务器建立了一个 TCP 连接后是否会在一个 HTTP 请求完成后断开?什么情况下会断开?

在 HTTP/1.0 中,一个服务器在发送完一个 HTTP 响应后,会断开 TCP 链接。

但是这样每次请求都会重新建立和断开 TCP 连接,代价过大。所以虽然标准中没有设定,某些服务器对 Connection: keep-alive 的 Header 进行了支持。意思是说,完成这个 HTTP 请求之后,不要断开 HTTP 请求使用的 TCP 连接。这样的好处是连接可以被重新使用,之后发送 HTTP 请求的时候不需要重新建立 TCP 连接,以及如果维持连接,那么 SSL 的开销也可以避免。

HTTP/1.1 就把 Connection 头写进标准,并且默认开启持久连接,除非请求中写明 Connection: close,那么浏览器和服务器之间是会维持一段时间的 TCP 连接,不会一个请求结束就断掉。

所以默认情况下建立 TCP 连接不会断开,只有在请求报头中声明 Connection: close 才会在请求完成后关闭连接。

参考:

面试官问我:一个 TCP 连接可以发多少个 HTTP 请求?我竟然回答不上来...

一个 TCP 连接可以对应几个 HTTP 请求?

首先了解现代浏览器在与服务器建立了一个-tcp-连接后是否会在一个-http-请求完成后断开?什么情况下会断开?,然后得知答案肯定不只1个了,如果维持连接,一个 TCP 连接是可以发送多个 HTTP 请求的。

参考:

面试官问我:一个 TCP 连接可以发多少个 HTTP 请求?我竟然回答不上来...

一个 TCP 连接中 HTTP 请求发送可以一起发送么(比如一起发三个请求,再三个响应一起接收)?

HTTP/1.1 存在一个问题,单个 TCP 连接在同一时刻只能处理一个请求,意思是说:两个请求的生命周期不能重叠,任意两个 HTTP 请求从开始到结束的时间在同一个 TCP 连接里不能重叠。

虽然 HTTP/1.1 规范中规定了 Pipelining 来试图解决这个问题,但是这个功能在浏览器中默认是关闭的。

但是在实践中会出现许多问题:

  • 一些代理服务器不能正确的处理 HTTP Pipelining。

  • 正确的流水线实现是复杂的。

  • Head-of-line Blocking 连接头阻塞:在建立起一个 TCP 连接之后,假设客户端在这个连接连续向服务器发送了几个请求。按照标准,服务器应该按照收到请求的顺序返回结果,假设服务器在处理首个请求时花费了大量时间,那么后面所有的请求都需要等着首个请求结束才能响应。

所以现代浏览器默认是不开启 HTTP Pipelining 的。

但是,HTTP2 提供了 Multiplexing 多路传输特性,可以在一个 TCP 连接中同时完成多个 HTTP 请求。至于多路复用,参考http2多路复用是什么-解决了什么问题?

所以在 HTTP/1.1 存在 Pipelining 技术可以完成这个多个请求同时发送,但是由于浏览器默认关闭,所以可以认为这是不可行的。在 HTTP2 中由于 Multiplexing 特点的存在,多个 HTTP 请求可以在同一个 TCP 连接中并行进行

参考:

面试官问我:一个 TCP 连接可以发多少个 HTTP 请求?我竟然回答不上来...

TCP的流量控制机制

TCP 提供了流量控制的服务,这个服务的主要目的是控制发送方的发送速率, 保证接收方来得及接收。因为一旦发送的速率大 于接收方所能接收的速率,就 会造成报文段的丢失。接收方主要是通过接收窗口来告诉发送方自己所能接收的 大小,发送方根据 接收方的接收窗口的大小来调整发送窗口的大小,以此来达 到控制发送速率的目的。

TCP的拥塞控制机制

TCP 的拥塞控制主要是根据网络中的拥塞情况来控制发送方数据的发送速率,如果网络处于拥塞的状态,发送方就减小发送的 速率,这样一方面是为了避免 继续增加网络中的拥塞程度,另一方面也是为了避免网络拥塞可能造成的报文段 丢失。

TCP 的拥塞控制主要使用了四个机制,分别是慢启动、拥塞避免、快速重传和 快速恢复

慢启动的基本思想是,因为在发送方刚开始发送数据的时候,并不知道网络中的 拥塞程度,所以先以较低的速率发送,进行试探 ,每次收到一个确认报文,就 将发动窗口的长度加一,这样每个 RTT 时间后,发送窗口的长度就会加倍。当 发送窗口的大小达 到一个阈值的时候就进入拥塞避免算法。

拥塞避免算法是为了避免可能发生的拥塞,将发送窗口的大小由每过一个 RTT 增长一倍,变为每过一个 RTT ,长度只加一。 这样将窗口的增长速率由指数 增长,变为加法线性增长。

快速重传指的是,当发送方收到三个冗余的确认应答时,因为 TCP 使用的是累 计确认的机制,所以很有可能是发生了报文段的 丢失,因此采用立即重传的机 制,在定时器结束前发送所有已发送但还未接收到确认应答的报文段。

快速恢复是对快速重传的后续处理,因为网络中可能已经出现了拥塞情况,所以 会将慢启动的阀值减小为原来的一半,然后将拥 塞窗口的值置为减半后的阀值, 然后开始执行拥塞避免算法,使得拥塞窗口缓慢地加性增大。简单来理解就是, 乘性减,加性增。

TCP 认为网络拥塞的主要依据是报文段的重传次数,它会根据网络中的拥塞程 度,通过调整慢启动的阀值,然后交替使用上面四 种机制来达到拥塞控制的目的。

参考:

程序员面试必考题(十八)--TCP的拥塞控制机制 - 简书

为什么有的时候刷新页面不需要重新建立 SSL 连接?

先明白现代浏览器在与服务器建立了一个-tcp-连接后是否会在一个-http-请求完成后断开?什么情况下会断开?,由于TCP可以维持,所以SSL自然可以保持连接。

参考:

面试官问我:一个 TCP 连接可以发多少个 HTTP 请求?我竟然回答不上来...

浏览器对同一 Host 建立 TCP 连接到数量有没有限制?

假设我们还处在 HTTP/1.1 时代,那个时候没有多路传输,当浏览器拿到一个有几十张图片的网页该怎么办呢?肯定不能只开一个 TCP 连接顺序下载,那样用户肯定等的很难受,但是如果每个图片都开一个 TCP 连接发 HTTP 请求,那电脑或者服务器都可能受不了,要是有 1000 张图片的话总不能开 1000 个TCP 连接吧,你的电脑同意 NAT 也不一定会同意。

所以答案是:有。Chrome 最多允许对同一个 Host 建立六个 TCP 连接。不同的浏览器有一些区别。

参考:

面试官问我:一个 TCP 连接可以发多少个 HTTP 请求?我竟然回答不上来...

收到的 HTML 如果包含几十个图片标签,这些图片是以什么方式、什么顺序、建立了多少连接、使用什么协议被下载下来的呢?

如果图片都是 HTTPS 连接并且在同一个域名下,那么浏览器在 SSL 握手之后会和服务器商量能不能用 HTTP2,如果能的话就使用 Multiplexing 功能在这个连接上进行多路传输。不过也未必会所有挂在这个域名的资源都会使用一个 TCP 连接去获取,但是可以确定的是 Multiplexing 很可能会被用到。

如果发现用不了 HTTP2 呢?或者用不了 HTTPS(现实中的 HTTP2 都是在 HTTPS 上实现的,所以也就是只能使用 HTTP/1.1)。那浏览器就会在一个 HOST 上建立多个 TCP 连接,连接数量的最大限制取决于浏览器设置,这些连接会在空闲的时候被浏览器用来发送新的请求,如果所有的连接都正在发送请求呢?那其他的请求就只能等等了。

参考:

面试官问我:一个 TCP 连接可以发多少个 HTTP 请求?我竟然回答不上来...

TCP粘包是什么?

TCP是流协议,根本不存在所谓粘包一说。粘包并不是 TCP 协议造成的,它的出现是因为应用层协议设计者对 TCP 协议的错误理解,忽略了 TCP 协议的定义并且缺乏设计应用层协议的经验。

粘包问题出现的核心原因:

1、TCP 协议是基于字节流的传输层协议,其中不存在消息和数据包的概念;

2、应用层协议没有使用基于长度或者基于终结符的消息边界,导致多个消息的粘连;

所以“粘包”其实是应用程序中没有处理好数据包分割,两个应用层的数据包粘在一块了。

参考:

为什么 TCP 协议有粘包问题 - 面向信仰编程

怎么解决TCP网络传输「粘包」问题? - 知乎

UDP

简单介绍下UDP

UDP 是一种无连接的,不可靠的传输层协议。

它只提供了传输层需要实现的最 低限度的功能,除了复用/分解功能和少量的差错检测外,它几乎没有对IP增加其他的东西。

UDP 协议适用于对实时性要求高的应用场景。

使用 UDP 时,在发送报文段之前,通信双方没有握手的过程,因此 UDP 被称为是无连接的传输层协议。因为没有握手 过程,相对于 TCP 来说, 没有建立连接的时延。因为没有连接,所以不需要在端系统中保存连接的 状态。

UDP 提供尽力而为的交付服务,也就是说 UDP 协议不保证数据的可靠 交付。

UDP 没有拥塞控制和流量控制的机制,所以 UDP 报文段的发送速率没 有限制。

因为一个 UDP 套接字只使用目的地址和目的端口来标识,所以 UDP 可 以支持一对一、一对多、多对一和多对多的交互 通信。

UDP 首部小,只有 8 个字节。

DNS

简单介绍下DNS

DNS 协议提供的是一种主机名到 IP 地址的转换服务,就是我们常说的域名系统。它是一个由分层的 DNS 服务器组成的分 布式数据库,是定义了主机如何 查询这个分布式数据库的方式的应用层协议。DNS 协议运行在 UDP 协议之上, 使用 53 号 端口。

简单说下DNS解析的过程

DNS解析的过程就是一个网址到IP地址的转换。

DNS解析是一个递归查询的过程。流程图如下:

上述图片是查找www.google.com的IP地址过程。首先在本地域名服务器(路由器->运营商)中查询IP地址,如果没有找到的情况下,本地域名服务器会向根域名服务器发送一个请求,如果根域名服务器也不存在该域名时,本地域名会向com顶级域名服务器发送一个请求,依次类推下去。直到最后本地域名服务器得到google的IP地址并把它缓存到本地,供下次查询使用。从上述过程中,可以看出网址的解析是一个从右向左的过程: com -> google.com -> www.google.com。但是你是否发现少了点什么,根域名服务器的解析过程呢?事实上,真正的网址是www.google.com.,并不是我多打了一个.,这个.对应的就是根域名服务器,默认情况下所有的网址的最后一位都是.,既然是默认情况下,为了方便用户,通常都会省略,浏览器在请求DNS的时候会自动加上,所有网址真正的解析过程为: . -> .com -> google.com. -> www.google.com.

为了加快查找速度,会有DNS缓存

DNS存在着多级缓存,从离浏览器的距离排序的话,有以下几种: 浏览器缓存,系统缓存,路由器缓存,IPS服务器缓存,根域名服务器缓存,顶级域名服务器缓存,主域名服务器缓存

  • 在你的chrome浏览器中输入:chrome://dns/,你可以看到chrome浏览器的DNS缓存。
  • 系统缓存主要存在/etc/hosts(Linux系统)中:

为了避免全部指向同一机器,会使用DNS负载均衡

DNS可以返回一个合适的机器的IP给用户,例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等,这种过程就是DNS负载均衡,又叫做DNS重定向。大家耳熟能详的CDN(Content Delivery Network)就是利用DNS的重定向技术,DNS服务器会返回一个跟用户最接近的点的IP地址给用户,CDN节点的服务器负责响应用户的请求,提供所需的内容。

什么叫递归DNS和权威DNS?

DNS(Domain Name System)是一个全球化的分布式数据库,用于存储域名与互联网 IP 地址的映射关系。DNS 分为两大类:权威 DNS,递归 DNS。

权威 DNS

权威 DNS 是特定域名记录(例如 “example.com”)在域名注册商处所设置的 DNS 服务器,用于特定域名本身的管理(增加、删除、修改等)。

权威 DNS 服务器只对自己所拥有的域名进行域名解析,对于不是自己的域名则拒绝访问。比如,向 “example.com” 的权威 DNS 服务器查询 “test.com” 的域名肯定会查询失败。

阿里云云解析 DNS 提供权威 DNS 托管服务。

递归 DNS

递归 DNS(也称本地 DNS 或者缓存 DNS)用于域名查询。递归 DNS 会迭代权威服务器返回的应答,直至最终查询到的 IP 地址,将其返回给客户端,并将请求结果缓存到本地。

对用户发出的域名解析请求,递归 DNS 必须给出一个最终的 IP 地址结果。完整的递归 DNS 查询流程需要 DNS 服务器从根域名 “.” 服务器,顶级域名服务器(例如 “.com”),一级域名服务器(例如 “example.com”)等一级一级递归查询,直到最终找到权威服务器取得结果,并返回给客户。同时,递归服务器根据域名 TTL,缓存查询结果,便于相同域名重复查询。递归 DNS 的访问过程如下图所示(递归 DNS 在图中表示为 Local DNS)

递归 DNS 服务器大多数在运营商端,负责网络接入终端的 DNS 查询,即网络访问设备上配置的 DNS 服务器 IP。

综上,

  • 权威 DNS 由域名解析服务商建设,提供域名管理服务,维护域名解析记录。
  • 递归 DNS 由网络运营商建设,提供域名查询解析服务。

你工作中哪些场景使用的DNS相关技术?

首先明白简单说下dns解析的过程

每一个url,都会经历dns,参考浏览器中输入url到页面呈现到底发生了什么?

在负载均衡方面,也会用到dns轮询相关技术,参考如何针对接入层制定最佳解决方案?

在cdn方面,其实也是dns-server来通过用户id来决定将哪个机房的nginxip给用户,参考cdn的原理是什么?

DNS基于TCP还是UDP,为什么?

DNS 不仅使用了 UDP 协议,也使用了 TCP 协议,网络分层和常见协议?中也有记载。

DNS 查询的类型不止包含 A 记录、CNAME 记录等常见查询,还包含 AXFR 类型的特殊查询,这种特殊查询主要用于 DNS 区域传输,它的作用就是在多个命名服务器之间快速迁移记录,由于 DNS 区域传输的功能对于数据的准确有着较强的需求,所以我们必须使用 TCP 或者其他的可靠协议来处理 AXFR 类型的请求;

参考:

为什么 DNS 使用 UDP 协议 - 面向信仰编程

其他

网络分层和常见协议?

一张图解决问题:

简单说一下网络层是干嘛的?

网络层协议主要实现了不同主机间的逻辑通信功能。网络层协议一共包含两个主 要的组件,一个 IP 网际协议,一个是路由选 择协议。

IP 网际协议规定了网络层的编址和转发方式,比如说我们接入网络的主机都会 被分配一个 IP 地址,常用的比如 IPV4 使用 32 位来分配地址,还有 IPv6 使 用 128 位来分配地址。

路由选择协议决定了数据报从源到目的地所流经的路径,常见的比如距离向量路 由选择算法等。

简单说一下数据链路层是干嘛的?

数据链路层提供的服务是如何将数据报通过单一通信链路从一个结点移动到相 邻节点。每一台主机都有一个唯一的 MAC 地址, 这是由网络适配器决定的, 在全世界都是独一无二的。

简单说一下物理层是干嘛的?

物理层提供的服务是尽可能的屏蔽掉组成网络的物理设备和传输介质间的差异,使数据链路层不需要考虑网络的具体传输介质 是什么。

参考:

搞定计算机网络面试,看这篇就够了(补充版)

ping ip到发包,发送了什么?

首先根据目的IP和路由表决定走哪个网卡,再根据网卡的子网掩码地址判断目的IP是否在子网内。

如果在相同网段直接先查询arp缓存,如果找到目标ip的mac地址,直接发送出去。 如果缓存中查不到,则从相同网段的网卡发arp问目标ip的mac地址,拿到mac地址后发送出去。

如果不在主机的网段里,会查询默认网关ip,接着查询arp缓存,是否有网关的mac地址记录,如果有,填充该mac地址,发送出去, 如果没有,发arp问网关的mac地址,得到结果,发送出去。

谈谈CDN服务

CDN 是一个内容分发网络,通过对源网站资源的缓存,利用本身多台位于不同地域、不同运营 商的服务器,向用户提供资就近访问的功能。

也就是说,用户的请求并不是直接发送给源网站,而是发送给 CDN 服务器,由 CND 服 务器将请求定位到最近的含有该资源的服务器上去请求。

这样有利于提高网站的访问速度,同时通过这种方式也减轻了源服务器的访问压力。

完整过程如下:

1.首先访问本地的 DNS ,如果没有命中,继续递归或者迭代查找,直到命中拿到对应的 IP 地址。

2.拿到对应的 IP 地址之后服务器端发送请求到目的地址。注意这里返回的不直接是 cdn 服务器的 IP 地址,而是全局负载均衡系统的 IP 地址

4.全局负载均衡系统会根据客户端的 IP地址和请求的 url 和相应的区域负载均衡系统通信

5.区域负载均衡系统拿着这两个东西获取距离客户端最近且有相应资源的cdn 缓存服务器的地址,返回给全局负载均衡系统

6.全局负载均衡系统返回确定的 cdn 缓存服务器的地址给客户端。

7.客户端请求缓存服务器上的文件

参考:

CDN是什么?使用CDN有什么优势? - 知乎

CDN的原理是什么?

根据客户端ip来分配最近的服务器机房访问,

(1)电信用户想要访问某一个服务器资源

(2)浏览器向dns-server发起服务器域名解析请求

(3)dns-server识别出访问者是电信用户

(4)dns-server将电信机房的nginx外网ip返回给访问者

(5)访问者就近访问

有没有了解过cdn的边缘计算?

传统的CDN服务是纯粹的缓存和分发服务,缺乏可以直接提供给您的计算能力。访问CDN的海量请求中,复杂的计算逻辑必须回服务器源站执行,这增加了您的服务器消耗以及架构的复杂性。ER可提供直接在CDN边缘节点计算处理的能力,将极大提高CDN的可定制化,可编程化,从而大量减少需回源的请求,降低用户的请求延时。同时CDN边缘节点拥有天然的高可用、高伸缩、全球负载均衡的特性,边缘的计算服务可应用于更多的使用场景。阿里云CDN的ER可为您提供边缘节点的计算环境,为您的代码部署提供更多的选择。

参考:

功能介绍_边缘程序_CDN - 阿里云

MAC地址是唯一的吗?相同的MAC地址会有什么影响?为什么?

MAC 地址(Media access control address)是分配给网络接口控制器(Network interface controller, NIC)的唯一标识符,它会在网络段中充当网络地址使用1,所有具有网卡的主机都有单独的 MAC 地址,该地址总共包含 48 位,占 6 字节的空间,可以表示 281,474,976,710,656 个网络设备,一个正常的 MAC 地址如下所示的格式表示,每个字节都会使用两位 16 进制的数字:

6e:77:0f:b8:8b:6b

MAC 地址需要保证唯一,所以 IEEE 会根据设备的制造商分配地址段,48 位 MAC 地址的前 24 位是设备制造商的标识符2,也就是组织唯一标识符(Organizationally Unique Identifier,OUI),后面的 24 位是序列号;如果每个设备制造商都能保证在同一个命名空间中的全部 MAC 地址唯一,那么全世界所有的 MAC 地址就可以保证唯一。

然而在实际的网络场景中,我们不需要保证如此强的限制:

MAC 地址可以通过软件进行修改,而第三方的山寨厂商不会在 IEEE 中申请独立的 MAC 地址段,它们也可能会盗用其他厂商申请的 MAC 地址;

如果保证 MAC 地址在局域网中唯一就不会造成网络问题,不同局域网中的 MAC 地址可以相同;

至于局域网内MAC为什么要唯一,参考局域网内机器互联的原理?

参考:

为什么 Mac 地址不需要全球唯一 - 面向信仰编程

局域网内机器互联的原理?

局域网中的数据传输不是通过网络层的 IP 地址进行路由和转发的,然而 IP 地址一般都是发送数据主机知道的唯一信息,想要在局域网中发送数据,还是需要知道它们的 MAC 地址。当我们的设备想要向其他的设备发送数据时,它会先通过 ARP(Address Resolution Protocol,地址解析协议) 在局域网中获取目的 IP 地址对应的 MAC 地址。

在局域网中我们一般会使用集线器(Hub)或者交换机(Switch)来连接不同的网络设备。因为在集线器连接的局域网中,所有的数据帧都会被广播给局域网内的全部主机,所以使用相同的 MAC 地址一般也不会出现太多的问题;但是交换机会学习局域网中不同设备的 MAC 地址并将数据帧转发给特定主机,所以如果局域网是由交换机构成的,就会影响网络的通信。

假设局域网中的具有两台 MAC 地址完全相同的网络设备 A 和 B,即 6e:77:0f:b8:8b:6b,当设备 A 想要向设备 B 发送以太网帧时会遇到如下所示的情况:

1、设备 A 在构造的以太网帧中将源地址和目的地址都设置为 6e:77:0f:b8:8b:6b 并向交换机发送数据;

2、交换机接收到了设备 A 发送的数据帧后,会从数据帧的源地址学习到设备 A 的 MAC 地址并将 6e:77:0f:b8:8b:6b -> A 这条记录插入本地缓存中;

3、交换机发现收到数据帧的目的地址会指向了网络设备 A,所以它会将该数据转发回 A;

因为交换机的 MAC 地址学习策略,所以我们不能在同一个局域网中使用相同的 MAC 地址,但是因为 MAC 地址是链路层网络中的概念,跨局域网的网络传输需要通过网络层的 IP 协议,所以在不同的局域网中使用相同的 MAC 地址就不存在类似的问题了。

参考:

为什么 Mac 地址不需要全球唯一 - 面向信仰编程

WebSocket

发起webSocket的流程,能简述一下吗?

首先,WebSocket连接必须由浏览器发起,因为请求协议是一个标准的HTTP请求,格式如下:

GET ws://localhost:3000/ws/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Origin: http://localhost:3000
Sec-WebSocket-Key: client-random-string
Sec-WebSocket-Version: 13

该请求和普通的HTTP请求有几点不同:

GET请求的地址不是类似/path/,而是以ws://开头的地址;

请求头Upgrade: websocket和Connection: Upgrade表示这个连接将要被转换为WebSocket连接;

Sec-WebSocket-Key是用于标识这个连接,并非用于加密数据;

Sec-WebSocket-Version指定了WebSocket的协议版本。

随后,服务器如果接受该请求,就会返回如下响应:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: server-random-string

该响应代码101表示本次连接的HTTP协议即将被更改,更改后的协议就是Upgrade: websocket指定的WebSocket协议。

参考:

Node.js 有难度的面试题,你能答对几个? - 云+社区 - 腾讯云

Socket和http的区别?

socket连接:

socket不属于协议范畴,而是一个调用接口(API),是对TCP/IP协议的封装。实现服务器与客户端之间的物理连接,并进行数据传输。Socket处于网络协议的传输层,主要有TCP/UDP两个协议。

而websocket协议是一个完整的应用层协议,拥有一套完整的API。

socket连接是长连接,理论上客户端和服务器端一旦建立起连接将不会主动断掉;但是由于各种环境因素可能会是连接断开,比如:服务器端或客户端主机宕机了、网络故障,或者两者之间长时间没有数据传输,网络防火墙可能会断开该连接以释放网络资源。所以当一个socket连接中没有数据的传输,那么为了维持连接需要发送心跳消息。

socket传输的数据可自定义,为字节级,数据量小,可以加密,数据安全性高,适合Client/Server之间信息实时交互。

http连接:

HTTP是基于TCP/IP协议的应用层协议,定义的是传输数据的内容的规范。

HTTP是基于请求-响应形式并且是短连接,即客户端向服务器端发送一次请求,服务器端响应后连接即会断掉。

HTTP是无状态的协议,针对其无状态特性,在实际应用中又需要有状态的形式,因此一般会通过session/cookie技术来解决此问题。

HTTP的传输速度慢,数据包大,数据传输安全性差,如实现实时交互,服务器性能压力大。

参考:

套接字Socket的常见面试题及答案 - 知乎

websocket应用场景?

1、社交订阅

2、多玩家游戏

3、协同编辑文档

4、数据流状态

5、多人聊天

http2的服务端推送可以取代websocket吗?

首先了解http2的服务器推送是什么,如何实现?

据我了解,HTTP/2 不是 websocket 的替代品,而是旨在标准化 SPDY 协议。

在 HTTP/2 中,服务器推送在幕后用于改善客户端从浏览器加载资源。作为开发人员,您在开发过程中并不真正关心它。但是,通过 Websocket,开发人员可以使用 API,该 API 能够通过独特的全双工连接来消费和推送消息。

这些不是一回事,应该是相辅相成的。

参考:

http2 - Does HTTP/2 make websockets obsolete? - Stack Overflow

除了websocket,还有哪些服务端主动push的方法?

websocket是全双工的,占用的资源会多一些。除了websocket,还可以使用EventSource API,来进行服务端向客户端的的单向主动通信。用法如下:

var evtSource = new EventSource('sse.php');
var eventList = document.querySelector('ul');

evtSource.onmessage = function(e) {
  var newElement = document.createElement("li");

  newElement.textContent = "message: " + e.data;
  eventList.appendChild(newElement);
}

EventSource的缺点就是不能客户端到服务端,只能服务端到客户端,且只支持utf8。

还可以通过http2的服务端推送功能。但是和这个不是针对应用程序API级别,而是文件资源级别,一般用来预加载静态资源用。

参考:

EventSource - Web API 接口参考 | MDN