实验要求
实现1个钟表程序(服务),多个用户可以从该程序获得时间并在本地显示,用户也可以修改时间。
(1)用户程序可以在计算机上运行,也可以在手机上运行;
(2)至少3个用户程序可同时运行,时间每秒钟刷新;
(3) 1个用户修改了时间,所有用户的时间都要随着被改变;
(4) 推荐使用JavaScript、node.js、Websocket,以及Nginx实现;
(5) 可能存在跨域问题。
实验步骤
1. 准备环境和安装依赖:
计算机上安装 Node.js 和 npm。
创建一个新的文件夹,比如 "realtime-server",进入该文件夹。
在终端中执行以下命令以初始化一个新的 Node.js 项目:
npm init -y
安装所需的依赖:
npm install express http ws moment cors
2. 编写代码:
创建一个名为 server.js
的文件,并将提供的代码复制粘贴到该文件中。
3. 运行服务器:
在终端中运行以下命令启动服务器:
node server.js
4. 连接到服务器:
可使用任何支持 WebSocket 的客户端连接到该服务器。可以使用浏览器的控制台或者 WebSocket 客户端工具,如 wscat
。
打开浏览器控制台或运行 wscat -c ws://localhost:8080
(确保端口号与服务器代码中指定的一致)连接到服务器。
5. 接收当前时间:
一旦连接建立,服务器会发送当前时间给客户端。
6. 发送消息更新时间:
在客户端(浏览器控制台或 wscat
)中发送一个符合 ISO 8601 格式的时间字符串,服务器会更新时间并广播给所有连接的客户端。
7. 观察时间更新:
你会看到连接的客户端接收到新的时间,并且每秒钟都会更新一次。
8. 测试不合法时间:
尝试发送一个不符合 ISO 8601 格式的字符串到服务器,你会看到服务器会打印出 "Invalid date format" 的错误信息。
9.结束实验:
关闭服务器,按下 Ctrl + C
终止运行 node server.js
的命令。
这样就能成功地建立了一个实时时间更新的 WebSocket 服务器,并能够通过客户端与其进行交互。
程序代码
服务端server.js
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const moment = require('moment');const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
const cors = require('cors');let currentTime = moment();
let modifiedTime = null; // 变量用于存储用户修改后的时间
app.use(cors());wss.on('connection', (ws) => {ws.send(currentTime.toISOString());ws.on('message', (message) => {const messageStr = message.toString(); // 将接收到的消息转换为字符串if (moment(messageStr, moment.ISO_8601, true).isValid()) {modifiedTime = moment(messageStr);currentTime = modifiedTime; // 更新当前时间为用户修改后的时间wss.clients.forEach((client) => {if (client.readyState === WebSocket.OPEN) {client.send(currentTime.toISOString());}});} else {console.log('Invalid date format:', messageStr);}});
});setInterval(() => {if (modifiedTime) {currentTime = modifiedTime;} else {currentTime = moment();}wss.clients.forEach((client) => {if (client.readyState === WebSocket.OPEN) {client.send(currentTime.toISOString());}});
}, 1000);server.listen(8080, () => {console.log('Server started on port 8080');
});
客户端Real-clock.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Real-time Clock</title><script src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
</head>
<body><h1 id="clock"></h1><label for="newTime">Enter New Time:</label><input type="datetime-local" id="newTime" placeholder="YYYY-MM-DDTHH:mm"><button onclick="updateTime()">Update Time</button><script>const socket = new WebSocket('ws://localhost:8080');socket.onmessage = function(event) {const currentTime = moment(event.data).format('YYYY-MM-DD HH:mm:ss');document.getElementById('clock').innerText = currentTime;};function updateTime() {const inputDateTime = document.getElementById('newTime').value;const formattedDateTime = moment(inputDateTime, 'YYYY-MM-DDTHH:mm').toISOString();socket.send(formattedDateTime);}setInterval(() => {socket.send('update');}, 1000);</script>
</body>
</html>
实验截图
打开 HTML 页面:
将提供的 HTML 代码保存为Real-clock.html 文件,并在浏览器中打开。
2. 初始显示:
页面加载后,你会看到一个标题为 "Real-time Clock" 的页面,以及一个空白的时钟显示区域和一个用于输入新时间的输入框。
钟表程序
3. 连接到服务器:
页面加载后,客户端会尝试连接到 ws://localhost:8080
这个 WebSocket 服务器。
4. 接收当前时间:
一旦连接建立,服务器会发送当前时间给客户端,并显示在页面上的时钟区域。
三个浏览器窗口模拟三个进程
三个浏览器窗口模拟三个进程
5. 输入新时间:
在 "Enter New Time" 输入框中输入一个新的时间,格式为 "YYYY-MM-DDTHH
",例如 "2024-06-15T10:00"。
6. 更新时间:
点击 "Update Time" 按钮,客户端会将新时间发送到服务器,服务器接收并更新时间。
7. 观察时钟更新:
页面上的时钟区域会显示为新输入的时间。
8. 定时更新:
每隔一秒,客户端会向服务器发送一个 "update" 消息,服务器会将当前时间发送回客户端,页面上的时钟区域会持续更新。
9. 结束交互:
关闭浏览器标签或停止服务器,结束交互。
存在的问题:
在这个实验中,存在一些潜在的问题和改进空间:
- 时区处理:当前实现中并未考虑时区的处理,如果需要支持不同时区的用户,需要进一步处理时区转换和显示。
- 客户端错误处理:客户端发送的新时间格式错误时,并未提供友好的提示,用户可能无法得知输入的格式有误。
- 服务器端数据持久化:当前实现中,服务器端并未对时间数据进行持久化,一旦服务器重启,时间会被重置。可以考虑使用数据库或者其他持久化方式来保存时间数据。
实验展望:
虽然这个实验已经实现了基本的实时时间更新功能,但仍有一些方面可以进一步改进和扩展:
- 用户体验优化:可以进一步改进页面布局和交互方式,使用户能够更方便地输入新时间,并提供更友好的界面反馈。
- 安全性考虑:在生产环境中,需要考虑 WebSocket 连接的安全性,防止恶意攻击和非授权访问。可以考虑添加身份验证、消息加密等安全机制。
- 性能优化:当前的实现每秒都向客户端发送时间更新,即使时间并未发生变化。可以通过在服务器端和客户端实现更智能的逻辑,减少不必要的数据传输,从而提升性能和效率。
实验总结:
在这个实验中,我们成功地构建了一个实时时间更新的 WebSocket 服务器,并通过一个 HTML 页面与之进行交互。以下是实验的主要收获和总结:
- 功能实现:通过使用 Express、WebSocket 和 Moment.js 等技术,我们成功地创建了一个实时时间更新的服务器,并能够通过 WebSocket 实现与客户端的实时通信。
- 页面交互:在 HTML 页面中,我们通过 WebSocket 接收来自服务器的时间更新,并能够通过输入框向服务器发送新的时间来更新时钟显示。
- 定时更新:我们实现了定时向服务器发送更新请求的功能,以保持页面上的时钟实时更新。
(笔者将会非常感谢大家来完善这个程序!)