WebSocket
- WebSocket 是 HTML5 新增的一种
全双工通信协议
,客户端和服务器基于 TCP 握手连接成功后,两者之间就可以建立持久性的连接,实现双向数据传输。 - HTTP 协议是一种单向的网络协议,在建立连接后,它允许客户端向服务器发送请求资源后,服务器才会返回相应的数据,而服务器不能主动推送数据给客户端。
-
(短)轮询(Polling)
短轮询模式下,客户端每隔一段时间向服务器发送 HTTP
请求。服务器收到请求后,将最新的数据发回给客户端。弊端:某个时间段服务器没有更新内容,但是客户端每隔一段时间发送请求来询问,而这段时间内的请求是无效的。
-
长轮询
长轮询模式下,客户端向服务器发出请求,服务器并不一定会立即回应客户端,而是查看数据是否有更新。如果数据更新了的话,那就立即发送数据给客户端;如果没有更新,那就保持这个请求,等待有新的数据到来,才将数据返回给客户端。如果服务器长时间没有更新,那么一段时间后,请求变会超时,客户端收到消息后,会立即发送一个新的请求给服务器。
弊端:当服务器向客户端发送数据后,必须等待下一次请求才能将新的数据发出,这样客户端接收新数据就有一个最短时间间隔。如果服务器更新频率较快,那么就会出现问题。
WebSocket和HTTP对比
- 都需要建立 TCP 连接;都属于七层协议中的应用层协议。
HTTP
是单向数据流,客户端向服务器发送请求,服务器响应并返回数据;WebSocket
连接后可以实现客户端和服务器双向数据传递,除非某一端断开连接。HTTP
的 url 使用 http//
或者 https//
开头,而 WebSocket
的 url 使用 ws//
开头。
CDN
CDN
全称 Content Delivery Network
,即内容分发网络。
-
其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。让 CDN 服务商判断用户举例它哪个资源库最近,就提供哪个地址给用户。
-
不使用 CDN
广州的用户 jsliang 要请求一个在北京的 IP 地址。
那可能经过是这样的:广州用户 -> 广州服务器 -> 湖南服务器 -> 湖北服务器 -> 北京服务器。这样子一个一个查找,就很耽搁时间。
-
使用 CDN
北京服务器指定了一个 CDN 服务商,然后这个服务商有个广州服务器上做了部署,我们直接访问广州服务器就可以找到资料了。
-
正向代理
:用户是知道服务器 IP 地址的,但是自己访问不了,需要别人帮忙访问。
我是一个用户,我访问不了某网站,但是我能访问一个代理服务器。这个代理服务器访问那个我不能访问的网站,代理服务器去取回来,然后返回给我。
-
反向代理
:用户是不知道具体请求到的服务器的 IP 地址的。
反向代理即在客户端和服务器之间推出一个代理服务器,然后所有请求内容都经过代理服务器去管理。用户在访问的时候,就访问总服务器的地址(公网 IP),然后总服务器去分配具体的小服务器(私网 IP)去处理你的请求。
如何解决跨域问题?
-
使用 jsonp 来实现跨域请求,
- 它的主要原理是通过动态构建 script 标签来实现跨域请求,因为浏览器对 script 标签的引入没有跨域的访问限制 。
- 通过在请求的 url 后指定一个回调函数,然后服务器在返回数据的时候,构建一个 json 数据的包装,这个包装就是回调函数,然后返回给前端,前端接收到数据后,因为请求的是脚本文件,所以会直接执行,这样我们先前定义好的回调函数就可以被调用,从而实现了跨域请求的处理。
- 优点:兼容性好,能解决主流浏览器跨域访问的问题。
- 缺点:只能用于 get 请求。而且不安全,可能会遭受 XSS 攻击。
-
使用 CORS 的方式
- 跨域资源共享CORS,它允许浏览器向跨源服务器,发出 XMLHttpRequest 或 Fetch 请求。目前浏览器都支持这个功能,只需要服务端设置
Access-Control-Allow-Origin
就可以开启 CORS。
简单请求和复杂请求的区别:
- 简单请求 的发送从代码上看起来和普通的 XHR 没太大区别,但是 HTTP 头当中要求总是包含一个域(Origin)的信息。该域包含协议名、地址以及一个可选的端口。Origin 字段用来说明本次请求来自哪个源。服务器根据这个值,决定是否同意这次请求。如果成功的话服务器会返回包含一些以 Access-Control- 开头的字段。否则服务器会返回一个正常的一般的 HTTP 回应,浏览器再抛出错误。
- 复杂请求 不止发送一个请求。其中最先发送的是一种 “预请求”,来判断该域名是否在服务器的白名单中,如果收到服务器的肯定回复后才会发起请求。
-
使用 postMessage
- 通过获取到指定窗口的引用,然后调用 postMessage 来发送信息, 在窗口中我们通过对 message 信息的监听来接收信息,以此来实现不同源间的信息交换。
- 可解决:页面和其打开的新窗口的数据传递、多窗口之间消息传递、页面与嵌套的 iframe 消息传递。
- 如果是像解决 ajax 无法提交跨域请求的问题,我们可以使用 jsonp、cors、websocket 协议、 服务器代理来解决问题。
-
websocket 协议
- 这个协议没有同源限制。
- 它实现了浏览器与服务器的全双工通信,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。
-
使用Node
- 同源策略是浏览器需要遵循的标准,而如果是服务器向服务器请求就无需遵循同源策略。
- 所以我们可以通过
Node
中间件代码(两次跨域): - 接受客户端请求 → 将请求转发给服务器 → 拿到服务器响应数据 →将响应转发给客户端
-
使用代理服务器
- 有跨域的请求操作时发送请求给后端,让后端代为请求,然后最后将获取的结果发返回。因为服务器的没有跨域接口的限制的。
-
document.domain
- 将 document.domain 设置为主域名,来实现相同子域名的跨域操作,这个时候主域名下 的 cookie 就能够被子域名所访问。同时如果文档中含有主域名相同,子域名不同的 iframe 的话,我们也可以对这个 iframe 进行操作。 如果是想要解决不同跨域窗口间的通信问题,比如说一个页面想要和页面的中的不同源的 iframe 进行通信的问题,我们可以使用 location.hash 或者 window.name 或者 postMessage 来解决。
-
location.hash
- 使用 location.hash 的方法,我们可以在主页面动态的修改 iframe 窗口的 hash 值, 然后在 iframe 窗口里实现监听函数来实现这样一个单向的通信。因为在 iframe 是没有办法 访问到不同源的父级窗口的,所以我们不能直接修改父级窗口的 hash 值来实现通信,我们可 以在 iframe 中再加入一个 iframe ,这个 iframe 的内容是和父级页面同源的,所以我们可 以 window.parent.parent 来修改最顶级页面的 src,以此来实现双向通信。
-
window.name
- 使用 window.name 的方法,主要是基于同一个窗口中设置了 window.name 后不同源的 页面也可以访问,所以不同源的子页面可以首先在 window.name 中写入数据,然后跳转到一 个和父级同源的页面。这个时候级页面就可以访问同源的子页面中 window.name 中的数据了, 这种方式的好处是可以传输的数据量大。