WebSocket
普通的包的请求和响应过程
1. 对 WebSocket 的理解
WebSocket是HTML5提供的一种浏览器与服务器进行全双工通讯的网络技术,属于应用层协议。它基于TCP传输协议,并复用HTTP的握手通道。浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接, 并进行双向数据传输。
WebSocket 的出现就解决了半双工通信的弊端。它最大的特点是:服务器可以向客户端主动推动消息,客户端也可以主动向服务器推送消息。
WebSocket原理:客户端向 WebSocket 服务器通知(notify)一个带有所有接收者ID(recipients IDs)的事件(event),服务器接收后立即通知所有活跃的(active)客户端,只有ID在接收者ID序列中的客户端才会处理这个事件。
WebSocket 特点的如下:
● 支持双向通信,实时性更强
● 可以发送文本,也可以发送二进制数据‘’
● 建立在TCP协议之上,服务端的实现比较容易
● 数据格式比较轻量,性能开销小,通信高效
● 没有同源限制,客户端可以与任意服务器通信
● 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL
● 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
Websocket的使用方法如下:
在客户端中:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<p id="mes"></p>
<script>
let pText = document.querySelector("p");
let ws = new WebSocket("ws://localhost:3000/", ["com.kaazing.echo"]);
ws.onopen = (e) => {
console.log("WebSocket open", e);
setInterval(() => {
ws.send(new Date().getTime());
}, 2000);
};
ws.onmessage = ({ data }) => {
pText.innerText = data;
};
</script>
</body>
</html>
node服务器中
// npm install ws --save
const express = require("express");
const http = require("http");
const Ws = require("ws").Server;
const app = express();
const server = http.createServer(app);
server.listen(3000);
app.use(express.static("www"));
let wsServer = new Ws({ server });
wsServer.on("connection", function (socket) {
console.log("连接成功");
socket.on("message", (msg) => {
console.log("客户端信息", msg);
socket.send("客户端发送的信息:" + msg + "," + new Date().getTime());
});
});
2. 即时通讯的实现:短轮询、长轮询、SSE 和 WebSocket 间的区别?
短轮询和长轮询的目的都是用于实现客户端和服务器端的一个即时通讯。
短轮询的基本思路:浏览器每隔一段时间向服务器发送 http 请求,服务器端在收到请求后,不论是否有数据更新,都直接进行响应。这种方式实现的即时通信,本质上还是浏览器发送请求,服务器接受请求的一个过程,通过让客户端不断的进行请求,使得客户端能够模拟实时地收到服务器端的数据的变化。这种方式的优点是比较简单,易于理解。缺点是这种方式由于需要不断的建立 http 连接,严重浪费了服务器端和客户端的资源。当用户增加时,服务器端的压力就会变大,这是很不合理的。
长轮询的基本思路:首先由客户端向服务器发起请求,当服务器收到客户端发来的请求后,服务器端不会直接进行响应,而是先将这个请求挂起,然后判断服务器端数据是否有更新。如果有更新,则进行响应,如果一直没有数据,则到达一定的时间限制才返回。客户端 JavaScript 响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。长轮询和短轮询比起来,它的优点是明显减少了很多不必要的 http 请求次数,相比之下节约了资源。长轮询的缺点在于,连接挂起也会导致资源的浪费。
SSE 的基本思想:服务器使用流信息向服务器推送信息。严格地说,http 协议无法做到服务器主动推送信息。但是,有一种变通方法,就是服务器向客户端声明,接下来要发送的是流信息。也就是说,发送的不是一次性的数据包,而是一个数据流,会连续不断地发送过来。这时,客户端不会关闭连接,会一直等着服务器发过来的新的数据流,视频播放就是这样的例子。SSE 就是利用这种机制,使用流信息向浏览器推送信息。它基于 http 协议,目前除了 IE/Edge,其他浏览器都支持。它相对于前面两种方式来说,不需要建立过多的 http 请求,相比之下节约了资源。
WebSocket 是 HTML5 定义的一个新协议议,与传统的 http 协议不同,该协议允许由服务器主动的向客户端推送信息。使用 WebSocket 协议的缺点是在服务器端的配置比较复杂。WebSocket 是一个全双工的协议,也就是通信双方是平等的,可以相互发送消息,而 SSE 的方式是单向通信的,只能由服务器端向客户端推送信息,如果客户端需要发送信息就是属于下一个 http 请求了。
上面的四个通信协议,前三个都是基于HTTP协议的。
对于这四种即使通信协议,从性能的角度来看:
WebSocket > 长连接(SEE) > 长轮询 > 短轮询
但是,我们如果考虑浏览器的兼容性问题,顺序就恰恰相反了:
短轮询 > 长轮询 > 长连接(SEE) > WebSocket
所以,还是要根据具体的使用场景来判断使用哪种方式。