Websocket 你了解吗?

326 阅读2分钟

前言

为什么需要Websocket呢?

已经有了HTTP协议,为什么还需要另外一个websocket协议呢?

原因:

  1. 因为http协议中,通信只能由客户端发起,做不到服务端主动向客户端推送信息
  2. 对于一些服务端状态发送变化,客户端需要获知的场景,虽然可以通过轮询(每隔一段时间,就会发出一个请求,询问服务端是否更新信息)获知,但是轮询的效率十分低,需要http连接始终打开,浪费资源

那么websocket是如何解决的呢?

websocket 介绍

简介

Websocket 是html5提供的一种浏览器与服务器进行全双工通讯的网络技术,属于应用层协议

websocket基于tcp传输协议,并复用http握手通道,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性连接,并进行双向数据通信。

image.png

[注意]: 为什么websocket只需要完成一次握手,就可以建立连接?

答: websocket的握手和tcp的三次握手不是一个层次的握手, websocket的握手是在tcp三次握手建立连接完成之后进行的,主要是为了告知服务器这是一个websocket连接。

特点

  1. 最大的特点就是: 客户端可以主动向浏览器发送信息,服务器也可以主动向客户端推送信息
  2. 基于tcp传输协议
  3. 没有同源限制,客户端可以与任意的服务端通信
  4. 协议标识符是 ws(加密,则为wss)
  5. 可以发送文本,也可以发送二进制数据
  6. 与http协议有着良好的兼容性,默认端口也是80和443,并且握手阶段采用的是http协议

缺点

存在兼容性

image.png

websocket使用的场景

  1. 跨域的方法之一就是使用websocket进行跨域请求
  2. 当服务器有连续的状态变化,客户端需要获知,其中的方法之一也可以使用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);
});

实现效果

未命名.gif

总结

服务器向客户端推送信息,除了Websocket,还有一种方式:Server-Sent Events

上述只简单的实现了websocket的demo,想了解websocket的更多内容可以查看MDN developer.mozilla.org/zh-CN/docs/…