NodeJS 中的 Web Socket 入门

2025-06-04

NodeJS 中的 Web Socket 入门

在直播、视频会议和远程办公盛行的时代,任何用户最关心的问题之一就是延迟。无缝体验才是关键。

传统的 HTTP 依赖于客户端请求,根本无法满足这一需求。它们实在太慢了。它确实需要升级。

让我来介绍一下 Websockets——一种事件驱动、Web 友好的 HTTP 替代方案。Websockets 无需客户端每次都从服务器请求获取数据,从而满足了实时更新的需求。想知道它是如何实现的吗?让我们来一探究竟。


什么是 Websockets?

简单来说,websockets是对传统HTTP的升级。

每当向常规 HTTP 发出 WebSocket 请求时,它实际上都会升级为 WebSocket 连接。然而,这仅发生在协议级别,这意味着底层 TCP 连接将与使用 HTTP 协议时保持一致。

  1. 为了使用 websocket,客户端首先发送升级服务器的请求。

  2. 如果服务器支持 websocket(现在通常都支持),它将接受请求并将协议从 HTTP 切换到 websocket。

  3. 一旦协议切换成功,http服务器就变成websocket服务器,并且在客户端和服务器之间建立持久连接。

  4. 接下来,WebSocket 服务器等待事件发生,一旦事件发生,便执行与该事件相关的函数。例如,在聊天应用中,您无需每次都请求下一条消息。由于是 WebSocket 连接(事件驱动),服务器只需将收到的每条新消息(事件)直接推送到客户端即可。

WebSockets主要用于需要实时更新的地方。例如:

  1. 聊天应用程序。
  2. 基于位置的应用程序。
  3. 社交信息流。
  4. 合作工作。
  5. 多人游戏。
  6. 現場直播。
  7. 财经和体育更新。

以上所有功能都得益于 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.jsJS 文件将作为客户端。


实现服务器

现在让我们编写服务器端的 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
PREV
使用 Javascript 和 Twilio 发送短信
NEXT
Understanding map, filter, and zip in Python Understanding map, filter, and zip in Python