NodeJS 中的 Web Socket 入门
在直播、视频会议和远程办公盛行的时代,任何用户最关心的问题之一就是延迟。无缝体验才是关键。
传统的 HTTP 依赖于客户端请求,根本无法满足这一需求。它们实在太慢了。它确实需要升级。
让我来介绍一下 Websockets——一种事件驱动、Web 友好的 HTTP 替代方案。Websockets 无需客户端每次都从服务器请求获取数据,从而满足了实时更新的需求。想知道它是如何实现的吗?让我们来一探究竟。
什么是 Websockets?
简单来说,websockets是对传统HTTP的升级。
每当向常规 HTTP 发出 WebSocket 请求时,它实际上都会升级为 WebSocket 连接。然而,这仅发生在协议级别,这意味着底层 TCP 连接将与使用 HTTP 协议时保持一致。
-
为了使用 websocket,客户端首先发送升级服务器的请求。
-
如果服务器支持 websocket(现在通常都支持),它将接受请求并将协议从 HTTP 切换到 websocket。
-
一旦协议切换成功,http服务器就变成websocket服务器,并且在客户端和服务器之间建立持久连接。
-
接下来,WebSocket 服务器等待事件发生,一旦事件发生,便执行与该事件相关的函数。例如,在聊天应用中,您无需每次都请求下一条消息。由于是 WebSocket 连接(事件驱动),服务器只需将收到的每条新消息(事件)直接推送到客户端即可。
WebSockets主要用于需要实时更新的地方。例如:
- 聊天应用程序。
- 基于位置的应用程序。
- 社交信息流。
- 合作工作。
- 多人游戏。
- 現場直播。
- 财经和体育更新。
以上所有功能都得益于 WebSocket,从而提升了用户体验。WebSocket 始终保持其状态(不同于无状态的 HTTP),并采用全双工连接。此外,WebSocket 中的标头在发送升级请求时仅发送一次。正因如此,WebSocket 的速度比传统 HTTP 快 5 到 7 倍。
听起来很激动?确实如此,但这仅仅是理论上的。没有什么比亲眼见证它的实际效果,甚至亲自实现它更棒的了。那就让我们开始吧。
设置开发环境
首先,我们需要安装所需的文件和软件包,并创建工作区来设置开发环境。我们将使用 ws 库在 NodeJS 中创建一个简单的基于 WebSocket 的聊天应用程序。
首先,在项目文件夹中创建两个名为 client 和 server 的文件夹。
现在启动节点终端并转到服务器目录并逐个运行以下命令
npm init -y
//初始化节点并创建 package.json 文件
npm install websocket
//安装 websocket 库
npm install ws
//安装 ws 库 - 一个 websocket 实现
npm install express
//安装 express 来创建一个简单的 http 服务器
npm install nodemon
//安装 nodemon 包来跟踪代码的变化并重新启动服务器
完成后,index.js
在服务器文件夹中创建一个名为的文件。这index.js
将是我们的服务器端 JavaScript 文件。
现在我们转到客户端文件夹。在客户端文件夹中,创建一个名为 的文件index.html
,以及另一个名为 的文件script.js
。HTML 文件将作为应用程序的前端,而script.js
JS 文件将作为客户端。
实现服务器
现在让我们编写服务器端的 JavaScript。index.js
在服务器文件夹中添加以下代码。
const WebSocket = require("ws"); | |
const express = require("express"); | |
const app = express() | |
const path = require("path") | |
app.use("/",express.static(path.resolve(__dirname, "../client"))) | |
const myServer = app.listen(9876) // regular http server using node express which serves your webpage | |
const wsServer = new WebSocket.Server({ | |
noServer: true | |
}) // a websocket server | |
wsServer.on("connection", function(ws) { // what should a websocket do on connection | |
ws.on("message", function(msg) { // what to do on message event | |
wsServer.clients.forEach(function each(client) { | |
if (client.readyState === WebSocket.OPEN) { // check if client is ready | |
client.send(msg.toString()); | |
} | |
}) | |
}) | |
}) | |
myServer.on('upgrade', async function upgrade(request, socket, head) { //handling upgrade(http to websocekt) event | |
// accepts half requests and rejects half. Reload browser page in case of rejection | |
if(Math.random() > 0.5){ | |
return socket.end("HTTP/1.1 401 Unauthorized\r\n", "ascii") //proper connection close in case of rejection | |
} | |
//emit connection when request accepted | |
wsServer.handleUpgrade(request, socket, head, function done(ws) { | |
wsServer.emit('connection', ws, request); | |
}); | |
}); |
const WebSocket = require("ws"); | |
const express = require("express"); | |
const app = express() | |
const path = require("path") | |
app.use("/",express.static(path.resolve(__dirname, "../client"))) | |
const myServer = app.listen(9876) // regular http server using node express which serves your webpage | |
const wsServer = new WebSocket.Server({ | |
noServer: true | |
}) // a websocket server | |
wsServer.on("connection", function(ws) { // what should a websocket do on connection | |
ws.on("message", function(msg) { // what to do on message event | |
wsServer.clients.forEach(function each(client) { | |
if (client.readyState === WebSocket.OPEN) { // check if client is ready | |
client.send(msg.toString()); | |
} | |
}) | |
}) | |
}) | |
myServer.on('upgrade', async function upgrade(request, socket, head) { //handling upgrade(http to websocekt) event | |
// accepts half requests and rejects half. Reload browser page in case of rejection | |
if(Math.random() > 0.5){ | |
return socket.end("HTTP/1.1 401 Unauthorized\r\n", "ascii") //proper connection close in case of rejection | |
} | |
//emit connection when request accepted | |
wsServer.handleUpgrade(request, socket, head, function done(ws) { | |
wsServer.emit('connection', ws, request); | |
}); | |
}); |
实现客户端
完成了服务器端之后,我们就可以实现客户端了。我们从 开始index.html
。在其中添加以下代码。
<!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>WebSockets</title> | |
</head> | |
<body> | |
<!-- Simple HTML page for sending messages with input box and send button--> | |
<h1>Hello WebSockets</h1> | |
<div id="messages"></div> | |
<input type="text" id="message"> | |
<button id="send">Send Message</button> | |
<script src="script.js"></script> | |
</body> | |
</html> |
<!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>WebSockets</title> | |
</head> | |
<body> | |
<!-- Simple HTML page for sending messages with input box and send button--> | |
<h1>Hello WebSockets</h1> | |
<div id="messages"></div> | |
<input type="text" id="message"> | |
<button id="send">Send Message</button> | |
<script src="script.js"></script> | |
</body> | |
</html> |
转到 script.js 文件。向其中添加以下代码。
//Websocekt variables | |
const url = "ws://localhost:9876/myWebsocket" | |
const mywsServer = new WebSocket(url) | |
//DOM Elements | |
const myMessages = document.getElementById("messages") | |
const myInput = document.getElementById("message") | |
const sendBtn = document.getElementById("send") | |
sendBtn.disabled = true | |
sendBtn.addEventListener("click", sendMsg, false) | |
//Sending message from client | |
function sendMsg() { | |
const text = myInput.value | |
msgGeneration(text, "Client") | |
mywsServer.send(text) | |
} | |
//Creating DOM element to show received messages on browser page | |
function msgGeneration(msg, from) { | |
const newMessage = document.createElement("h5") | |
newMessage.innerText = `${from} says: ${msg}` | |
myMessages.appendChild(newMessage) | |
} | |
//enabling send message when connection is open | |
mywsServer.onopen = function() { | |
sendBtn.disabled = false | |
} | |
//handling message event | |
mywsServer.onmessage = function(event) { | |
const { data } = event | |
msgGeneration(data, "Server") | |
} |
//Websocekt variables | |
const url = "ws://localhost:9876/myWebsocket" | |
const mywsServer = new WebSocket(url) | |
//DOM Elements | |
const myMessages = document.getElementById("messages") | |
const myInput = document.getElementById("message") | |
const sendBtn = document.getElementById("send") | |
sendBtn.disabled = true | |
sendBtn.addEventListener("click", sendMsg, false) | |
//Sending message from client | |
function sendMsg() { | |
const text = myInput.value | |
msgGeneration(text, "Client") | |
mywsServer.send(text) | |
} | |
//Creating DOM element to show received messages on browser page | |
function msgGeneration(msg, from) { | |
const newMessage = document.createElement("h5") | |
newMessage.innerText = `${from} says: ${msg}` | |
myMessages.appendChild(newMessage) | |
} | |
//enabling send message when connection is open | |
mywsServer.onopen = function() { | |
sendBtn.disabled = false | |
} | |
//handling message event | |
mywsServer.onmessage = function(event) { | |
const { data } = event | |
msgGeneration(data, "Server") | |
} |
WebSockets 实际应用
就是这样!
当你部署你的应用时(确保服务器端和客户端都运行),你的 HTML 页面就会打开。如果你在输入框中输入任何内容并点击“发送消息”,服务器就会将消息回显给你。但这有什么乐趣呢?我们想看到两个客户端聊天。
打开另一个浏览器或同一浏览器的另一个实例。现在访问与上述相同的 URL。
将两个浏览器并排放置在屏幕上。现在,当您从一个浏览器发送消息时,它会反映在另一个浏览器上,并且也会在同一个浏览器中回显。您可以在两个浏览器中尝试相同的操作,结果相同。您会注意到,回显和另一个浏览器中的消息几乎同时出现。这就是您的 WebSocket 在工作。
好了!希望你觉得这个用 NodeJS 实现的 WebSocket 聊天应用简单易用,用起来很有趣。发挥你的创造力吧!
当您准备展示您的项目时,请将其部署在Codesphere上,这是唯一一个可以让您轻松配置云服务的云平台。
部署只需几分钟!
以上就是我们这边的全部内容。请在下方告诉我们,你打算构建什么精彩的实时应用程序!
文章来源:https://dev.to/codesphere/getting-started-with-web-sockets-in-nodejs-49n0