js快速搭建WebSocket前后端及语法基础

Last updated on 8 months ago

什么是 WebSocket

WebSocket 是一种网络传输协议。在传统模式中,客户端实现实时推送需要通过轮询(每个一段时间发起一次请求),而 WebSocket 就是为了解决这个问题而诞生,WebSocket 的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话

node.js 搭建 WebSocket 服务端

  • 创建项目
1
npm init -y
  • 安装 ws
1
npm install ws
  • 新建 index.js 并导入库
1
const WebSocket = require("ws");

下面是个简单的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const WebSocket = require("ws");

// 创建webcocket服务器
const wss = new WebSocket.WebSocketServer({ port: 8080 });

// 监听连接事件
wss.on("connection", function connection(ws) {
console.log("New connection");

// 监听消息事件
ws.on("message", (message) => {
console.log(`[Client]: ${message}`);
// 发送消息给客户端
ws.send("ok");
});

// 监听关闭事件
ws.on("close", () => {
console.log("Disconnected");
});
});

然后在终端输入

1
node index.js

启动服务器

客户端连接

如果想在浏览器中连接客户端,js 原生支持 WebSocket,也可以使用 sockeio 或其他的库。如果想要在 node 中以终端的形式运行,也可以继续使用上面的 ws


这里先讲在 node 下运行服务端
新建一个 client.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//导入ws
const WebSocket = require("ws");

// 新建连接
ws = new WebSocket("ws://localhost:8080");

// 监听open连接事件
ws.on("open", function () {
// 发送消息给服务端
ws.send("ok?");
});

// 监听消息接收事件:
ws.on("message", function (message) {
console.log(`[SERVER]:${message}`);
});

终端输入命令运行

1
node client.js

如果要在浏览器中连接,可以直接用原生的 WebSocket

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<head>
<title>WebSocket连接</title>
</head>
<body>
<input id="input" type="text" />
<button onclick="send()">发送消息</button>
</body>
<script>
// 新建WebSocket对象并建立连接
let ws = new WebSocket("ws://localhost:8080");

// 监听连接事件
ws.onopen = () => {
console.log("连接成功");
};

// 监听消息接收事件
ws.onmessage = (message) => {
console.log(message.data);
};

//发送消息
function send() {
let message = document.getElementById("input").value;
ws.send(message);
}
</script>

制作一个简单的聊天室

服务端 index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
const WebSocket = require("ws");

var clients = [];

// 创建WebSocket服务器
const wss = new WebSocket.Server({ port: 8080 });

// 监听连接事件
wss.on("connection", function connection(ws, req) {
console.log("New connection");

// 监听消息事件
ws.on("message", (message) => {
console.log("Received: %s", message);
// 如果消息以用户名开头,则解析用户名
if (String(message).startsWith("[username]")) {
const index = clients.findIndex((client) => client.ws === ws);
// 如果不是新用户则修改名字
if (index != -1) {
clients[index].name = message;
} else {
// 如果是新用户,则加入列表
const username = message.slice(10); // 去掉 '[username]' 前缀
clients.push({ ws, username });
}
} else {
// 否则,将消息发送给除发送者外的所有客户端
let index = clients.findIndex((client) => client.ws == ws);
let username = clients[index].username;
clients.forEach((client) => {
if (client.ws !== ws) {
client.ws.send(` [${username}]:${message}`);
}
});
}
});

// 监听关闭事件
ws.on("close", function () {
// 从列表删除用户
const index = clients.findIndex((client) => client.ws === ws);
console.log(`[${clients[index].username}]Disconnected`);
clients.splice(index, 1);
});
});

客户端 client.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
const WebSocket = require("ws");
const readline = require("readline");

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});

// WebSocket 连接的函数
function connect(name) {
const ws = new WebSocket("ws://localhost:8080");

ws.on("open", () => {
console.log("连接成功");
ws.send(`[username]${name}`);
});

ws.on("message", (message) => {
console.log("收到消息:%s", message);
});

// 发送消息的函数
function send() {
rl.question("发送:", (message) => {
ws.send(message);
send(); // 再次调用,继续监听用户输入
});
}

send(); // 启动发送消息功能
}

// 第一个问题输入用户名
rl.question("你的名字:", (name) => {
connect(name); // 开始 WebSocket 连接并启动消息发送
});

打开三个终端,启动一次 index.js 和两个 client.js

1
2
3
node idnex.js
node client.js
node client.js

在输入名字后就可以发送和接收消息了

原生 WebSocket 简单语法

只讲一些常用、简单的内容,具体内容请参考官方文档
WebSocket 对象提供了用于创建和管理 WebSocket 连接,以及可以通过该连接发送和接收数据的 API。


构造函数

1
var aWebSocket = new WebSocket(url[, protocols]);
  • 参数
    • url:要连接的服务器 URL

实例属性

binaryType

WebSocket.binaryType返回 websocket 连接所传输二进制数据的类型

  • 返回值
    返回一串 String - “blob”:传输的是 blob 类型的数据 - “arraybuffer”:传输的是 ArrayBuffer 类型的数据

bufferedAmount

WebSocket.bufferedAmount是一个只读属性,用于返回已经被send()方法放入队列但还没有发送的数据的字节数,当全部数据被发送完后就会被重置为 0,如果传输中途连接中断则不会重置

readyState

WebSocket.readyState是一个只读属性,返回 WebSocket 的链接状态

  • 返回值
    0-3 的数字用于表示不同的状态
    • 0(WebSocket.CONNETION):正在连接中
    • 1(WebSocket.OPEN):已经连接并且可以通讯
    • 2(WebSocket.CLOSE):连接正在关闭
    • 3(WebSocket.CLOSED):连接已经关闭或连接没有成功

url

WebSocket.url是一个只读属性,返回构造函数创建WebSocket实例对象时URL的绝对路线

  • 返回值
    string类型

实例方法

close()

WebSocket.close([code][,reason])关闭连接

  • 参数
    • 可选code:一个数字状态码,解释了连接关闭的原因,不传默认1005(表示没有收到预期的状态码),其他状态码可以查看官方文档
    • 可选reason:一个人类可读的字符串,解释连接关闭的原因,这个UTF-8编码的字符串不能超过123个字节
  • 抛出异常
    • INVALID_ACCESS_ERR:一个无效的code
    • SYNTAX_ERR:reason字符串太长

send()

WebSocket.send(data),将 需要发送的数据 添加到队列中,并根据所需要传输的data bytes的大小自行增加bufferedAmount的值。

  • 参数
    • data:传输至服务器的数据,必须是以下类型
      • USVString:文本字符串
      • ArrayBuffer:类型化数组对象发送底层二进制数据
      • Blob:Blob 类型将队列 blob 中的原始数据以二进制中传输
      • ArrayBufferView:你可以以二进制帧的形式发送任何 JavaScript 类数组对象
  • 异常
    • INVALID_STATE_ERR:连接未处于open状态
    • SYNTAX_ERR:数据是一个包含未配对代理的字符串

未配对代理 (unpaired surrogates) 指的是在字符串中存在不匹配的 Unicode 代理项。Unicode 中的代理项用于表示一些特殊字符,而代理项对通常是成对出现的,例如表示表情符号的代理对。如果一个字符串中的代理项没有配对,就会出现未配对代理的情况。

事件

响应事件可以用WebSocket中的属性或者使用js监听器

close

WebSocket.onclose属性返回一个事件监听器,当连接变为CLOSED的时候会被调用

1
2
3
WebSocket.onclose = function(event) {
console.log(event)
}

event中包含了时间戳、url、关闭的code等消息

error

当websocket的连接由于一些错误事件的发生 (例如无法发送一些数据) 而被关闭时,一个error事件将被引发。

1
2
3
4
5
const socket = new WebSocket("ws://localhost:8080");
socket.addEventListener("error", function(event) {
console.log(event)
})
socket.onerror = ...

message

接收新消息时触发

1
2
3
4
5
6
socket.onmessage = function(event) {
console.log(event)
}
socket.addEventListener("message",function(event) {
console.log(event)
})

event中包含了接收的消息data

open

建立连接时触发

1
2
3
socket.onopen = function(event) {
console.log(event)
}