• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

在 Node.js 服务器上使用 HTML5 WebSockets

html5 中最酷的特性之一是 WebSockets。WebSockets 允许我们与服务器通信,而不需要传统的 ajax 请求。

在本教程中,我们将学习很多关于 WebSockets 的知识。我们将构建一个通过 WebSockets 进行通信的客户端和服务器的实际示例。

什么是 WebSocket?

WebSockets 是一种通过一个 (TCP) 套接字进行双向通信的技术,是一种推送技术。

为什么我们需要 WebSockets?

应用程序不支持长轮询时,WebSockets 被广泛使用。通过长轮询,服务器会不断发送可能包含也可能不包含所需数据的回复。需要此数据来保持连接的新鲜和活跃。当客户端收到数据时,它会检查并在需要时提出另一个请求。当然,长轮询有多种好处和用例。但是,长轮询并不是客户端-服务器通信的最佳和最奇特的技术。如果连接超时,则需要重新连接。此外,长轮询会导致资源利用率非常低。 

这是需要推送技术的两个主要原因。正如它的名字所暗示的那样,只要有东西给客户端,服务器就会推送数据。这意味着客户不必定期提出请求。 

让我们从网络服务器开始我们的演示。这是一个简单的演示,可帮助您开始使用整个技术。 

1.构建 node.js 服务器

第 1 步:选择您的图书馆

对于 Node.js,您有十几个库可供选择来构建服务器。我最喜欢的是 ws,一个用于构建服务器的极其简单的库。该库允许我们创建服务器和客户端。多么酷啊? 

当然,使用 ws 的先决条件是安装 Node.js。所以,不要忘记在您的系统中下载并安装 Node.js。

接下来,您需要安装库。好吧,这是一个非常简单的工作,您可以运行以下命令:

npm install ws

然后打开最喜欢的代码编辑器,并创建一个名为index.js的文件。

第 2 步:创建 WebSocket 服务器

首先,您需要导入ws模块。这个比较简单。您必须键入以下行,这将确保将 ws 导入到您的应用程序中。

const WebSocket = require('ws')

接下来,您必须在端口上创建一个 Web 套接字服务器。客户端将通过此端口与服务器通信。在我们的例子中,端口号是 8081。

const wss = new WebSocket.Server({ port: 8081 })

那么,当客户端想要与服务器通信时应该怎么办呢?我们需要为此确定逻辑。ws 模块为以下每个状态更改提供了多个事件:

  • open

  • close

  • message

  • connection

  • upgrade

  • ping

此外,该模块还带有一些函数来触发和处理上述事件:

  1. on

  2. send

  3. onerror

在我们的简单服务器中,只要客户端连接,我们就会发出connection事件。要发出其中一个事件,我们可以使用该on函数。

wss.on('connection', function connection(ws) {});

万一出现错误,onerror可以使用该功能。下面是一个简短的示例,说明如何使用这些功能。

ws.on("close", () => { /* handle the event */ });
ws.onerror = function (error) { /* handle the error */ }

我们的 WebSocket 服务器的基本框架,打开和关闭端口 8081 以供客户端连接,如下所示:

const WebSocket = require('ws')
 
const wss = new WebSocket.Server({ port: 8081 })
 
wss.on('connection', function connection(ws) {
    ws.on("close", () => {
        console.log("Client disconnected");
    });
    ws.onerror = function () {
        console.log("Some Error occurred");
    }
});

第 3 步:接收消息

服务器只能对客户端执行这两种操作之一:发送消息或接收消息。首先,让我们看看如何从客户端接收消息。一旦建立了客户端和服务器连接,服务器就可以使用该message函数接收消息。 

Websocket 通信总是与框架一起发生。这些是数据片段,从客户端传输到服务器,反之亦然。并且,数据片段可以采用以下格式:

  • 文本 框: 这些包含原始文本形式的数据。

  • 二进制 数据帧: 这些包含二进制数据。

  • 乒乓帧:这些主要用于检查客户端和服务器之间是否建立了连接。浏览器通常负责响应这些消息。

  • 连接关闭 帧:这些用于握手连接关闭。

当浏览器与服务器对话时(在我们的例子中发生),将使用文本或二进制帧。客户端的.send()功能倾向于将消息作为二进制或文本数据发送。这包括各种格式,例如ArrayBuffer, 和Blob。您无需配置任何内容即可以特定格式发送数据。只需将其发送出去并在服务器上解码即可。 

同时,如果你想明确提及框架的类型,请使用.binaryType套接字的属性。

ws.binaryType = "arraybuffer"

如果要将缓冲区数据解码为字符串,可以使用以下函数。这里我们使用Buffer.from(), 然后.toString()将缓冲区转换为字符串。

ws.on("message", (msg) => {
    var buf = Buffer.from(msg);
    console.log(buf.toString());
});

第 4 步:向客户端发送消息

服务器的下一个功能是向客户端发送消息。为此,我们使用该功能。 ws.send()

现在我们已经确定并定义了服务器的基础知识,让我们构建应用程序,只要客户端与其连接,服务器就会向客户端发送消息。在下面的代码中,服务器'hello world' 每秒继续发送,直到客户端断开连接。 

向客户端发送消息就是这么简单。

const interval = setInterval(() => {
    ws.send('hello world')
}, 1000)

第 5 步:运行服务器

最后,您需要运行服务器。为此,您需要打开一个终端窗口,键入以下命令,并让服务器保持运行。不要忘记在文件夹中打开终端,其中存在在步骤 1 中创建的index.js 。

node index.js

并且,连接、断开连接、发送和接收消息的整个服务器代码如下所示:

const WebSocket = require('ws')
 
const wss = new WebSocket.Server({ port: 8081 })
 
wss.on('connection', function connection(ws) {
    console.log('Client connected')
     
    const interval = setInterval(() => {
        ws.send('hello world')
    }, 1000)
 
    ws.on("close", () => {
        console.log("Client disconnected");
    });
 
    ws.onerror = function () {
        console.log("Some Error occurred");
    }
     
    ws.on("message", (msg) => {
        var buf = Buffer.from(msg);
        console.log(buf.toString());
    });
});

2.建立客户

现在,服务器已启动并运行,是时候构建客户端了。为此,使用以下文件创建另一个 Node 项目: 

node_modules
index.html
index.js
package.json

第 1 步:安装库

就像我们如何安装 ws 来构建我们的服务器一样,您也必须在客户端包中安装 ws。您的package.json应该具有以下依赖项:

{
  "dependencies": {
    "ws": "^8.8.1"
  }
}

第 2 步:连接到 Web 服务器

为了连接到 Web 服务器,我们必须初始化一个新的 WebSocket。而且,网络套接字需要连接到构建网络服务器时定义的端口。在我们的例子中,它将再次是 8081。

var hostURL = "ws://localhost:8081";
webSocket = new WebSocket(hostURL);

主机 URL 包含三个重要部分。

  • 方案:ws

  • 主机:本地主机

  • 端口:8081

使用new WebSocket(url),连接会立即发生。在建立连接的过程中,客户端(又名浏览器)使用标头询问服务器是否支持 WebSockets。如果服务器响应为“是”,则建立连接,然后两人开始通话。使用的协议是 WebSocket 协议。在这里,我们根本不使用 HTTP 协议 !

在我们的客户端-服务器连接中,这里有一些请求标头。

GET ws://localhost:8081/ HTTP/1.1
Host: localhost:8081
Connection: Upgrade
.
.
Upgrade: websocket
.
Sec-WebSocket-Version: 13
.
.
Sec-WebSocket-Key: cBtV+sKFkk3wqmFFr909Vg==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
  • Connection: upgrade表示客户端需要切换协议。

  • Upgrade: websocket 提到请求的协议是“websocket”。

  • Sec-WebSocket-Key是浏览器生成的密钥。这是一个随机数,用于确保服务器支持 WebSocket 协议。它还可以防止各种代理缓存客户端和服务器之间进行的任何对话。

  • Sec-WebSocket-Version标识 WebSocket 协议的版本。最近的一个是13。

如果服务器同意建立连接,则响应为101。响应标头如下:

101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: abcd=
Sec-WebSocket-Accept

有一个使用非常特殊的算法生成的密钥。当浏览器(又名客户端)注意到这个密钥时,它就知道服务器实际上支持 WebSocket 协议。此后,数据可以以帧的形式传输。 

您无法模拟 WebSocket Handshakes。您不能使用fetch或XMLHttpRequest发出 HTTP 请求。为什么?因为 javascript 没有设置上面提到的 headers 的权限。

第 3 步:定义 WebSocket 事件

在我们定义我们的网络套接字事件之前,您需要更好地了解它们。在我们的客户端中,我们将使用三个不同的事件:

  • onOpen:套接字打开时触发的功能。

  • onMessage:从服务器接收到消息时触发的功能。

  • onClose:服务器关闭时触发的功能。

在 Node.js 服务器上使用 HTML5 WebSockets  第1张

必须使用WebSocket对象调用上述事件。

webSocket.onopen = function(){}
 
webSocket.onmessage = function(msg){}
 
webSocket.onclose = function(){}

在我们的演示中,客户端将连接到服务器并在 HTML 页面上显示从服务器接收到的任何消息。同样,从连接到断开的任何状态变化都将打印到 HTML 页面。为此,我们将编写一个connect方法,该方法将相应地实现 Web Socket 事件。

function connect(){
    try{
        webSocket = new WebSocket(hostURL);
        messageDiv.innerHTML = "<p>Socket status:" + websocketReadyStateArray[webSocket.readyState] + "</p>";
        webSocket.onopen = function(){
            messageDiv.innerHTML += "<p>Socket status:" + websocketReadyStateArray[webSocket.readyState] + "</p>";
            connectBtn.disabled = true;
            disconnectBtn.disabled = false;
        }
 
        webSocket.onmessage = function(msg){
            messageDiv.innerHTML += "<p>Server response : " + msg.data + "</p>";
        }
 
        webSocket.onclose = function(){
            messageDiv.innerHTML += "<p>Socket status:" + websocketReadyStateArray[webSocket.readyState] + "</p>";
            connectBtn.disabled = false;
            disconnectBtn.disabled = true;
        }
 
    }catch(exception){
        messageDiv.innerHTML += 'Exception happen, ' + exception;
    }
}

你可以看到我们的 connect 函数有一个 try/catch 块。将所有服务器通信包含在 try/catch 块中是一种良好的编码习惯。如果出现问题,我们需要有一个后备策略。并且,try/catch 为我们提供了这个!它为客户端提供了一种让用户知道连接出现问题的方法。它也是调试整体流程的好地方。 

在上述方法中,该onmessage函数的作用是在 HTML 页面上打印来自服务器的任何消息。 

第 4 步:桥梁

connect 函数不会立即启动客户端-服务器连接。我们可以看到 thewebsocket被定义了,但是messageDiv, connectBtn, disconnectBtn, 和的定义hostUrl似乎来自其他地方。 

我们将客户端代码分成两部分,init()和connect(). 函数负责init加载所有这些变量。而且,该init函数必须在页面加载时加载。init下面给出函数的定义。

function init(){
 
    messageDiv = document.getElementById("message");
    textInput = document.getElementById("text");
 
    hostURL = "ws://localhost:8081";
    websocketReadyStateArray = new Array('Connecting', 'Connected', 'Closing', 'Closed');
 
    connectBtn = document.getElementById('connect');
    disconnectBtn = document.getElementById('disconnect');
 
    connectBtn.disabled = false;
    sendTextBtn.disabled = true;
    sendJSONObjectBtn.disabled = true;
    disconnectBtn.disabled = true;
}

第 5 步:客户页面

客户端页面相当简单明了。我们将有以下内容:

  • adiv将加载来自服务器的消息的位置

  • 两个buttons 连接,并断开与服务器的连接

这是用于构建此页面的 HTML 代码。需要在index.html中输入:

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Html5 WebSockets Example</title>
<script type="text/JavaScript" src="index.js" charset="utf-8"></script>
<style>
    .block{
        display:block;
        margin-top: 10px;
    }
</style>
</head>
<body onload="init()">
<h3>Html5 WebSockets Example.</h3>
<div id="message" class="block"></div>
<button id="connect" onclick="connect()">Connect</button>
<button id="disconnect" onclick="disconnect()">Disconnect</button>
</body>
</html>

在 Node.js 服务器上使用 HTML5 WebSockets  第2张

建立连接后,客户端将从服务器收到“Hello World”。现在,页面将如下所示。

在 Node.js 服务器上使用 HTML5 WebSockets  第3张

客户端index.js中的完整代码如下:

var webSocket;
var messageDiv;
var textInput;
var hostURL;
var websocketReadyStateArray;
var connectBtn;
var disconnectBtn;
 
function init(){
 
    messageDiv = document.getElementById("message");
    textInput = document.getElementById("text");
 
    hostURL = "ws://localhost:8081";
    websocketReadyStateArray = new Array('Connecting', 'Connected', 'Closing', 'Closed');
 
    connectBtn = document.getElementById('connect');
    disconnectBtn = document.getElementById('disconnect');
 
    connectBtn.disabled = false;
    sendTextBtn.disabled = true;
    sendJSONObjectBtn.disabled = true;
    disconnectBtn.disabled = true;
}
  
function connect(){
    try{
        webSocket = new WebSocket(hostURL);
        messageDiv.innerHTML = "<p>Socket status:" + websocketReadyStateArray[webSocket.readyState] + "</p>";
        webSocket.onopen = function(){
            messageDiv.innerHTML += "<p>Socket status:" + websocketReadyStateArray[webSocket.readyState] + "</p>";
            connectBtn.disabled = true;
            disconnectBtn.disabled = false;
        }
 
        webSocket.onmessage = function(msg){
            messageDiv.innerHTML += "<p>Server response : " + msg.data + "</p>";
        }
 
        webSocket.onclose = function(){
            messageDiv.innerHTML += "<p>Socket status:" + websocketReadyStateArray[webSocket.readyState] + "</p>";
            connectBtn.disabled = false;
            disconnectBtn.disabled = true;
        }
 
    }catch(exception){
        messageDiv.innerHTML += 'Exception happen, ' + exception;
    }
}
 
function selectAll(){
    textInput.select();
}
  
function disconnect(){
    webSocket.close();
}

第 6 步:从客户端向服务器发送数据

直到,上面的这段代码,你将能够从服务器向客户端发送数据。为了将数据从客户端发送到服务器,您必须再执行几行代码。

我们将在我们的 HTML 页面中添加一个文本框,用户可以在其中输入数据。以及一个按钮,用于在单击时将文本框的内容发送到服务器。

<p class="block">Please input some text to Send : <input type="text" id="text" onfocus="selectAll()"/></p>
 
<!-- ... -->
 
<button id="sendMessage" onclick="sendMessage()">Send Message</button>

在 Node.js 服务器上使用 HTML5 WebSockets  第4张

单击按钮时,将调用以下方法向服务器发送消息。由于使用了 Web 套接字的默认框架,因此消息将作为Buffer. 

function sendMessage(){
    webSocket.send(textInput.value)
}

单击Send Message后,服务器的控制台中会显示以下内容,如下所示: 

在 Node.js 服务器上使用 HTML5 WebSockets  第5张

第 7 步:运行客户端

要运行客户端,您不必做太多事情。您需要在您喜欢的浏览器中打开index.html,然后单击“连接”与服务器建立连接。

而已!

结论

使用 HTML 和 javascript (NodeJS) 的 WebSockets 教程到此结束。WebSockets 非常令人高兴,并且在过去几年中发生了翻天覆地的变化。WS 只是众多可供选择的 Web 套接字库之一。您必须密切关注 W3C WebSocket api,以了解有关此 PUSH 技术的最新变化的所有信息。 

WebSocket 是一种建立浏览器-服务器连接的持久方法。这些没有跨源限制,并且在所有现代浏览器中都受支持。API 很简单,有 和 之类的.send方法.close。 


文章目录
  • 什么是 WebSocket?
  • 为什么我们需要 WebSockets?
  • 1.构建 node.js 服务器
      • 第 1 步:选择您的图书馆
      • 第 2 步:创建 WebSocket 服务器
      • 第 3 步:接收消息
      • 第 4 步:向客户端发送消息
      • 第 5 步:运行服务器
  • 2.建立客户
      • 第 1 步:安装库
      • 第 2 步:连接到 Web 服务器
      • 第 3 步:定义 WebSocket 事件
      • 第 4 步:桥梁
      • 第 5 步:客户页面
      • 第 6 步:从客户端向服务器发送数据
      • 第 7 步:运行客户端
  • 结论
  • 发表评论