当前位置: 首页 > news >正文

【前端】MQTT:通信与聊天室实战

本文是关于 MQTT.js 使用的详细长文教程。文章会循序渐进,从入门到进阶,涵盖常用功能、实用技巧以及代码示例,帮助读者深入理解如何在 JavaScript 环境中使用 MQTT 协议。整个教程将分为以下几个部分:

MQTT 协议

MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布/订阅协议,设计用于低带宽、不稳定网络环境,广泛应用于物联网(IoT)领域。它基于客户端-代理模式,支持三种消息质量服务(QoS)等级,能够满足不同场景的需求。

MQTT.js 安装

MQTT.js 是一个客户端库,用于在 JavaScript 中使用 MQTT 协议。它支持 Node.js 和浏览器环境,提供了简洁的 API,使得开发者能够快速集成 MQTT 协议。

  1. 使用 npm 安装(适用于 Node.js 环境):

    npm install mqtt --save
    
  2. 在浏览器环境中,可以通过 CDN 引入:

    <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
    

基础使用

连接到 MQTT 代理

首先,连接到 MQTT 代理服务器是使用 MQTT.js 的第一步。可以通过 mqtt.connect() 方法进行连接。

const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://broker.hivemq.com');client.on('connect', () => {console.log('Connected to MQTT broker');
});

在这个示例中,我们使用了 HiveMQ 的公共 MQTT 代理作为例子,你也可以将 mqtt://broker.hivemq.com 替换为你自己的代理地址。

订阅与发布消息

连接成功后,你可以订阅主题以接收消息,或者发布消息到指定主题。

订阅消息
client.subscribe('my/topic', (err) => {if (!err) {console.log('Subscribed to topic: my/topic');}
});
发布消息
client.publish('my/topic', 'Hello MQTT', (err) => {if (!err) {console.log('Message sent to my/topic');}
});

消息 QoS 等级

MQTT 协议支持三种 QoS 等级:

  • QoS 0:最多一次,不保证消息送达。
  • QoS 1:至少一次,保证消息送达,但可能重复。
  • QoS 2:只有一次,确保消息送达且不重复。
client.publish('my/topic', 'Hello QoS 1', { qos: 1 });

好的,我们来详细讲解如何在 Linux 服务器上部署 MQTT 代理(以 Mosquitto 为例),并设置用户名和密码管理。

MQTT.js 配置与管理

设置连接选项

你可以通过 connect() 方法的第二个参数传递配置项来定制连接选项,例如设置客户端ID、用户名、密码等。

const options = {clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8),username: 'user',password: 'password',keepalive: 60,clean: true
};const client = mqtt.connect('mqtt://broker.hivemq.com', options);

连接回调与错误处理

可以使用 on('connect')on('error') 等事件处理函数来监听连接状态:

client.on('connect', () => {console.log('Connected successfully');
});client.on('error', (err) => {console.error('Connection error: ', err);
});

连接与安全

使用 TLS 加密连接

为了确保连接的安全性,MQTT.js 支持通过 TLS 加密连接。你可以设置 mqtts:// 协议来使用加密连接。

const client = mqtt.connect('mqtts://broker.hivemq.com', {port: 8883,username: 'user',password: 'password'
});

MQTT 认证与授权

有些 MQTT 代理需要认证才能连接,MQTT.js 支持传递认证信息,如用户名和密码。

const options = {username: 'username',password: 'password'
};const client = mqtt.connect('mqtt://broker.hivemq.com', options);

高级功能与技巧

持久化会话与遗嘱消息

你可以通过配置持久化会话和遗嘱消息,增强客户端在断开连接后的一些行为。

const options = {clean: false,  // 保持会话will: {topic: 'last/will',payload: 'Client disconnected unexpectedly',qos: 1}
};const client = mqtt.connect('mqtt://broker.hivemq.com', options);

消息订阅与发布的优化

当你需要发布大量消息时,可以选择设置 QoS 0 来减少网络负担,或者使用 保留消息 来减少客户端的接收负担。

构建聊天室应用

技术栈

  • HTML/CSS/JavaScript:构建前端页面和交互
  • MQTT.js:通过 WebSocket 与 MQTT 代理进行消息通信
  • Bootstrap:用于布局和响应式设计(可选,但本教程不聚焦于其详细使用)

初始化项目

我们从一个简单的 HTML 文件开始,包含必要的依赖项。项目不依赖于任何后端,因此我们将使用免费的 MQTT 代理服务器进行通信。我们选择 broker.emqx.io,它是一个公开的 MQTT 代理,可以用于测试。

创建项目文件

在你计算机上创建一个文件夹,例如 mqtt-chatroom,然后在其中创建一个 HTML 文件,如 index.html

引入必要的库

首先,我们需要引入 MQTT.js 和 Bootstrap(用于美化布局和使其响应式):

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Responsive MQTT Chatroom</title><!-- 引入 Bootstrap --><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"><!-- 引入 MQTT.js --><script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
</head>
<body><div class="container mt-4"><h2 class="text-center">MQTT Chatroom</h2><!-- 聊天框区域 --><div id="chat" class="mb-4" style="height: 60vh; overflow-y: auto; background-color: #f8f9fa; border: 1px solid #ddd; padding: 10px;"></div><!-- 输入区域 --><div class="row"><div class="col-12 col-md-2 mb-2 mb-md-0"><input type="text" id="username" class="form-control" placeholder="Your Name"></div><div class="col-12 col-md-8 mb-2 mb-md-0"><input type="text" id="message" class="form-control" placeholder="Type your message here..."></div><div class="col-12 col-md-2"><button id="sendBtn" class="btn btn-primary btn-block">Send</button></div></div></div><script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script><script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

连接到 MQTT 代理

初始化 MQTT 连接

在前端页面加载时,我们需要通过 MQTT.js 连接到一个 MQTT 代理。此处我们使用 broker.emqx.io 作为测试代理。它支持 WebSocket 协议,允许我们通过浏览器与其通信。

在 HTML 文件中添加以下 JavaScript 代码来连接 MQTT 代理。

<script>// 连接到 MQTT 服务器const client = mqtt.connect("ws://broker.emqx.io:8083/mqtt");// 连接成功时的回调client.on("connect", () => {console.log("Connected to MQTT broker");});
</script>
处理连接

当连接成功后,我们将显示一条日志消息。你可以通过浏览器的控制台查看此信息。为了更好地管理连接,我们将通过 client.on('connect', ...) 回调函数确保连接成功。

发布和订阅消息

发布消息

聊天室的核心功能是能够发送消息并将其展示给所有订阅者。我们通过 MQTT.js 提供的 client.publish() 方法来实现发布消息。

为了让消息在聊天室中展示,我们将每个消息格式化为 JSON 对象,包含 usernamedata(即消息内容)。

<script>// 发送消息的函数function sendMessage() {const username = document.getElementById("username").value.trim();const message = document.getElementById("message").value.trim();if (username && message) {const payload = JSON.stringify({ username, data: message });client.publish("chatroom", payload);  // 发布到 chatroom 房间document.getElementById("message").value = "";  // 清空输入框} else {alert("Please enter both your name and a message.");}}document.getElementById("sendBtn").addEventListener("click", sendMessage);
</script>
订阅消息

为了接收并展示消息,我们需要订阅 chatroom 主题。当有新的消息到达时,client.on('message', ...) 事件会被触发,接收到的消息会被解析并显示到页面上。

<script>client.on("message", (topic, message) => {const { username, data } = JSON.parse(message.toString());const chat = document.getElementById("chat");const messageDiv = document.createElement("div");messageDiv.className = "message";messageDiv.innerHTML = `<span class="username">${username}:</span> ${data}`;chat.appendChild(messageDiv);chat.scrollTop = chat.scrollHeight;  // 滚动到底部});// 订阅 chatroom 主题client.subscribe("chatroom", () => {console.log("Subscribed to chatroom");});
</script>

实现房间选择功能

为了实现房间功能,我们允许用户切换聊天室(即订阅不同的主题)。我们添加一个按钮来选择房间,并通过弹窗输入新的房间名称来动态切换。

创建房间选择按钮

在页面的顶部,我们创建一个按钮,用于选择聊天室。点击按钮时会弹出一个对话框,允许用户输入新的房间名。

<div class="room-info"><button id="roomSelectButton" class="btn btn-secondary"><i class="fas fa-home"></i> Select Room</button><span>Current Room: <span id="roomName">chatroom</span></span>
</div>
监听房间选择操作

我们为按钮添加事件监听器,当用户选择新的房间时,我们将取消订阅当前房间并订阅新的房间。房间名将动态显示在页面上。

<script>let currentRoom = "chatroom";document.getElementById("roomSelectButton").addEventListener("click", () => {const newRoom = prompt("Enter new room name:", currentRoom);if (newRoom && newRoom !== currentRoom) {currentRoom = newRoom;client.unsubscribe(currentRoom); // 取消当前房间的订阅client.subscribe(currentRoom);   // 订阅新房间document.getElementById("roomName").textContent = currentRoom; // 更新房间名}});
</script>

增加房间切换后的清空消息

当切换房间时,我们希望清空当前聊天室的消息,以便用户看到新的房间消息。我们可以在 subscribe 之后清空消息列表。

client.on("message", (topic, message) => {const { username, data } = JSON.parse(message.toString());const chat = document.getElementById("chat");chat.innerHTML = "";  // 清空当前聊天内容const messageDiv = document.createElement("div");messageDiv.className = "message";messageDiv.innerHTML = `<span class="username">${username}:</span> ${data}`;chat.appendChild(messageDiv);
});

美化和响应式布局

为了让应用在不同设备上都能良好显示,我们使用 Bootstrap 提供的栅格系统来实现响应式布局。你可以

根据需要调整布局、按钮大小、字体等。

完整代码

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>My First Cesium App</title><!-- 加载 Cesium 的 CSS 样式 --><link href="https://cesium.com/downloads/cesiumjs/releases/1.111/Build/Cesium/Widgets/widgets.css" rel="stylesheet"><link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/css/bootstrap.css"><style>/* 设置页面和Cesium容器的大小 */html,body,#cesiumContainer {width: 100%;height: 100%;margin: 0;padding: 0;overflow: hidden;}</style></head><body><nav class="navbar navbar-expand-lg navbar-light bg-light"><div class="container"><a class="navbar-brand" href="#">Touken的网站</a><button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"aria-controls="navbarNav" aria-expanded="false" aria-label="切换导航"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbarNav"><ul class="navbar-nav ms-auto"><li class="nav-item dropdown"><a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"data-bs-toggle="dropdown" aria-expanded="false">产品</a><ul class="dropdown-menu" aria-labelledby="navbarDropdown"><li><a class="dropdown-item" href="game.html">命悬一线</a></li><li><a class="dropdown-item" href="chat.html">聊天室</a></li><li><a class="dropdown-item" href="#">产品C</a></li></ul></li><li class="nav-item dropdown"><a class="nav-link dropdown-toggle" href="#" id="navbarDropdownBlog" role="button"data-bs-toggle="dropdown" aria-expanded="false">博客</a><ul class="dropdown-menu" aria-labelledby="navbarDropdownBlog"><li><a class="dropdown-item" href="#">博客文章1</a></li><li><a class="dropdown-item" href="#">博客文章2</a></li><li><a class="dropdown-item" href="#">博客文章3</a></li></ul></li><li class="nav-item dropdown"><a class="nav-link dropdown-toggle" href="#" id="navbarDropdownResources" role="button"data-bs-toggle="dropdown" aria-expanded="false">资源</a><ul class="dropdown-menu" aria-labelledby="navbarDropdownResources"><li><a class="dropdown-item" href="#">资源1</a></li><li><a class="dropdown-item" href="#">资源2</a></li><li><a class="dropdown-item" href="#">资源3</a></li></ul></li><li class="nav-item"><a class="nav-link" href="#">关于我们</a></li><li class="nav-item"><a class="nav-link" href="#">联系我们</a></li></ul></div></div></nav><!-- Cesium 地图容器 --><div id="cesiumContainer"></div><!-- 加载 Cesium 的 JavaScript 文件 --><script src="https://cesium.com/downloads/cesiumjs/releases/1.111/Build/Cesium/Cesium.js"></script><script>Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmY2YzY2RmNS1iNDQ5LTRkMDEtOGViZi05OGM3MTVjOWU1NGEiLCJpZCI6MjQ3Mzk2LCJpYXQiOjE3Mjg2NDUwOTB9.PFfVhduoFk35Pw05-XXbqPms0m3Fo5KHL0pYVvtyRqg';const viewer = new Cesium.Viewer('cesiumContainer', {homeButton: false,sceneModePicker: false,baseLayerPicker: false,navigationHelpButton: false,animation: false,timeline: false,fullscreenButton: false,vrButton: false,infoBox: true,});// 注册左键点击事件viewer.screenSpaceEventHandler.setInputAction(function (movement) {const cartesian = viewer.camera.pickEllipsoid(movement.position);  // 使用 position 而不是 endPositionif (cartesian) {const cartographic = Cesium.Cartographic.fromCartesian(cartesian);const longitude = Cesium.Math.toDegrees(cartographic.longitude);const latitude = Cesium.Math.toDegrees(cartographic.latitude);alert(`经度: ${longitude.toFixed(6)}, 纬度: ${latitude.toFixed(6)}`);}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);// 隐藏商标  viewer._cesiumWidget._creditContainer.style.display = "none";  </script><script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script></body></html>

总结与展望

通过这篇教程,读者应该能够掌握 MQTT.js 的基础使用,理解 MQTT 协议的工作原理,并能够在自己的项目中有效地应用 MQTT.js。如果有任何问题,欢迎在评论区交流。


http://www.mrgr.cn/news/67237.html

相关文章:

  • PG实践|条件处理表达式函数及其操作
  • Day95 Docker
  • 【机器学习】k最近邻分类
  • OpenCV基础05_GUI和PyMsql
  • App运行流程分析
  • foreach 遍历List不产生GC的原因
  • 三十三、Python基础语法(面向对象其他语法-下)
  • 非关系型数据库NoSQL的类型与优缺点对比
  • 基于 Vue3、Vite 和 TypeScript 实现开发环境下解决跨域问题,实现前后端数据传递
  • 代码随想录第十八天| 530.二叉搜索树的最小绝对差 、 501.二叉搜索树中的众数 、236. 二叉树的最近公共祖先
  • 【FPGA】Verilog:理解德摩根第一定律: ( ̅A + ̅B) = ̅A x ̅B
  • 【真题笔记】21年系统架构设计师要点总结
  • dns服务器配置
  • Java项目实战II基于Spring Boot的问卷调查系统的设计与实现(开发文档+数据库+源码)
  • 源文件到可执行文件流程
  • LeetCode17. 电话号码的字母组合(2024秋季每日一题 59)
  • IDEA构建JavaWeb项目,并通过Tomcat成功运行
  • C语言程序的机器表示(逆向+函数调用栈详解版)
  • 【入门篇】2.10 串口打印Helloworld
  • VisionPro —— 颜色匹配工具详解
  • Linux APT 教程:从入门到精通
  • [C语言]多组输入的几种方法
  • 华为HD集群重启NAMENODE实例操作步骤
  • 交换机和集线器的区别
  • 软件测试面试题个人总结
  • 推荐程序员好用的浏览器插件