编写 WebSocket 客户端应用程序
注意:此功能在Web Workers中可用。
WebSocket 客户端应用程序使用WebSocket API通过 WebSocket 协议与WebSocket 服务器进行通信。
注意:本文中的示例代码片段取自我们的 WebSocket 聊天客户端/服务器示例。查看代码。
创建 WebSocket 对象
为了使用 WebSocket 协议进行通信,您需要创建一个WebSocket
对象;这将自动尝试打开与服务器的连接。
WebSocket 构造函数接受一个必需参数和一个可选参数
webSocket = new WebSocket(url, protocols);
url
-
要连接的 URL;这应该是 WebSocket 服务器将响应的 URL。这应该使用 URL 方案
wss://
,尽管某些软件可能允许您为本地连接使用不安全的ws://
。相对 URL 值以及https://
和http://
方案在大多数最新的浏览器版本中也允许。 protocols
可选-
单个协议字符串或协议字符串数组。这些字符串用于指示子协议,以便单个服务器可以实现多个 WebSocket 子协议(例如,您可能希望一个服务器能够根据指定的
protocol
处理不同类型的交互)。如果您没有指定协议字符串,则假定为空字符串。
如果目标不允许访问,则构造函数将抛出SecurityError
。如果您尝试使用不安全的连接,则可能会发生这种情况(大多数用户代理现在都要求所有 WebSocket 连接都使用安全链接,除非它们在同一设备上或可能在同一网络上)。
连接错误
如果在尝试连接时发生错误,则首先将error
事件发送到WebSocket
对象(从而调用任何处理程序),然后发送close
事件,指示连接关闭的原因。
浏览器还可以将其控制台输出更具描述性的错误消息,以及RFC 6455,第 7.4 节中定义的关闭代码,通过CloseEvent
。
示例
此简单示例创建一个新的 WebSocket,连接到wss://www.example.com/socketserver
处的服务器。在此示例中,在套接字请求中命名了一个自定义协议“protocolOne”,尽管可以省略。
const exampleSocket = new WebSocket(
"wss://www.example.com/socketserver",
"protocolOne",
);
返回后,exampleSocket.readyState
为CONNECTING
。一旦连接准备好传输数据,readyState
将变为OPEN
。
如果您想打开连接并且对您支持的协议灵活,则可以指定协议数组
const exampleSocket = new WebSocket("wss://www.example.com/socketserver", [
"protocolOne",
"protocolTwo",
]);
一旦建立连接(即readyState
为OPEN
),exampleSocket.protocol
将告诉您服务器选择了哪个协议。
建立 WebSocket 依赖于HTTP 升级机制,因此当我们将 Web 服务器地址为ws://www.example.com
或wss://www.example.com
时,协议升级请求是隐式的。
向服务器发送数据
打开连接后,您可以开始向服务器传输数据。为此,请对要发送的每条消息调用WebSocket
对象的send()
方法
exampleSocket.send("Here's some text that the server is urgently awaiting!");
您可以将数据作为字符串、Blob
或ArrayBuffer
发送。
由于建立连接是异步的并且容易发生故障,因此无法保证在创建 WebSocket 对象后立即调用send()
方法会成功。我们至少可以确定,尝试发送数据仅在建立连接后才发生,方法是定义一个onopen
事件处理程序来执行此操作
exampleSocket.onopen = (event) => {
exampleSocket.send("Here's some text that the server is urgently awaiting!");
};
使用 JSON 传输对象
您可以做的一件方便的事情是使用JSON向服务器发送相当复杂的数据。例如,聊天程序可以使用使用 JSON 封装数据包实现的协议与服务器交互
// Send text to all users through the server
function sendText() {
// Construct a msg object containing the data the server needs to process the message from the chat client.
const msg = {
type: "message",
text: document.getElementById("text").value,
id: clientID,
date: Date.now(),
};
// Send the msg object as a JSON-formatted string.
exampleSocket.send(JSON.stringify(msg));
// Blank the text input element, ready to receive the next line of text from the user.
document.getElementById("text").value = "";
}
接收来自服务器的消息
WebSockets 是一个事件驱动的 API;当接收到消息时,message
事件将发送到WebSocket
对象。要处理它,请为message
事件添加一个事件侦听器,或使用onmessage
事件处理程序。要开始侦听传入数据,您可以执行以下操作
exampleSocket.onmessage = (event) => {
console.log(event.data);
};
接收和解释 JSON 对象
让我们首先考虑使用 JSON 传输对象中提到的聊天客户端应用程序。客户端可能会接收各种类型的数据包,例如
- 登录握手
- 消息文本
- 用户列表更新
解释这些传入消息的代码可能如下所示
exampleSocket.onmessage = (event) => {
const f = document.getElementById("chatbox").contentDocument;
let text = "";
const msg = JSON.parse(event.data);
const time = new Date(msg.date);
const timeStr = time.toLocaleTimeString();
switch (msg.type) {
case "id":
clientID = msg.id;
setUsername();
break;
case "username":
text = `User <em>${msg.name}</em> signed in at ${timeStr}<br>`;
break;
case "message":
text = `(${timeStr}) ${msg.name} : ${msg.text} <br>`;
break;
case "rejectusername":
text = `Your username has been set to <em>${msg.name}</em> because the name you chose is in use.<br>`;
break;
case "userlist":
document.getElementById("userlistbox").innerText = msg.users.join("\n");
break;
}
if (text.length) {
f.write(text);
document.getElementById("chatbox").contentWindow.scrollByPages(1);
}
};
在这里,我们使用JSON.parse()
将 JSON 对象转换回原始对象,然后检查并对其内容采取行动。
文本数据格式
通过 WebSocket 连接接收的文本采用 UTF-8 格式。
关闭连接
完成使用 WebSocket 连接后,请调用 WebSocket 方法close()
exampleSocket.close();
在尝试关闭连接之前检查套接字的bufferedAmount
属性以确定网络上是否还有任何数据尚未传输可能会有所帮助。如果此值不为 0,则仍有待处理的数据,因此您可能希望等待后再关闭连接。
安全注意事项
WebSockets 不应在混合内容环境中使用;也就是说,您不应该从使用 HTTPS 加载的页面打开不安全的 WebSocket 连接,反之亦然。现在,大多数浏览器仅允许安全的 WebSocket 连接,并且不再支持在不安全的环境中使用它们。