前言
为什么需要Websocket呢?
已经有了HTTP协议,为什么还需要另外一个websocket协议呢?
原因:
- 因为http协议中,通信只能由客户端发起,做不到服务端主动向客户端推送信息
- 对于一些服务端状态发送变化,客户端需要获知的场景,虽然可以通过
轮询
(每隔一段时间,就会发出一个请求,询问服务端是否更新信息)获知,但是轮询的效率十分低,需要http连接始终打开,浪费资源
那么websocket是如何解决的呢?
websocket 介绍
简介
Websocket 是html5提供的一种浏览器与服务器进行全双工通讯的网络技术,属于应用层协议
websocket基于tcp传输协议,并复用http握手通道,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性连接,并进行双向数据通信。
[注意]: 为什么websocket只需要完成一次握手,就可以建立连接?
答: websocket的握手和tcp的三次握手不是一个层次的握手, websocket的握手是在tcp三次握手建立连接完成之后进行的,主要是为了告知服务器这是一个websocket连接。
特点
- 最大的特点就是:
客户端可以主动向浏览器发送信息,服务器也可以主动向客户端推送信息
- 基于tcp传输协议
- 没有同源限制,客户端可以与任意的服务端通信
- 协议标识符是 ws(加密,则为wss)
- 可以发送文本,也可以发送二进制数据
- 与http协议有着良好的兼容性,默认端口也是80和443,并且握手阶段采用的是http协议
缺点
存在兼容性
websocket使用的场景
- 跨域的方法之一就是使用
websocket
进行跨域请求 - 当服务器有连续的状态变化,客户端需要获知,其中的方法之一也可以使用
websocket
进行服务器推送
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>websocket client</title>
</head>
<body>
<script>
const ws = new WebSocket("ws://localhost:9999");
// 客户端和服务端建立连接后触发
ws.onopen = function (ev) {
console.log("Connection open ....");
ws.send("hello Websockets");
};
// 服务器给客户端发送信息时触发
ws.onmessage = function (ev) {
console.log("received message", ev.data);
};
// 关闭连接时触发
ws.onclose = function (ev) {
console.log("Connection close ....");
};
</script>
</body>
</html>
服务端代码实现
使用node + ws 模拟服务器实现
npm i ws -D
const ws = require("ws");
const webSocketServer = new ws.Server({ port: 9999 });
webSocketServer.on("listening", (socket) => {
console.log("web socket begins listening");
});
webSocketServer.on("connection", (socket, req) => {
socket.on("message", (data) => {
console.log('data', data);
if (data === "terminate") {
socket.close();
setTimeout(() => {
webSocketServer.close();
}, 3000);
}
});
socket.on("close", (code, reason) => {
console.log("Connect server close", code, reason);
});
socket.on("error", (error) => {
console.log("error", error);
});
const ip = req.connection.remoteAddress;
console.log((ip, "is connected"));
socket.send("hi");
setTimeout(() => {
socket.send("hi again");
}, 3000);
});
实现效果
总结
服务器向客户端推送信息,除了Websocket,还有一种方式:Server-Sent Events
上述只简单的实现了websocket的demo,想了解websocket的更多内容可以查看MDN developer.mozilla.org/zh-CN/docs/…