🚀 MQTT vs WebSocket:一文看懂关键差异与实战选型(附代码)

在构建实时应用(如即时通讯、物联网监控、股票行情推送)时,我们经常会面临一个经典的技术选型问题:到底是用 MQTT 还是 WebSocket?

很多开发者容易混淆这两者,甚至觉得它们是竞争关系。其实,它们更像是“高速公路”和“快递车队”的关系。今天我们就来彻底搞懂它们的区别,并附上简单的代码 Demo,帮你做出最正确的架构决策。


💡 核心概念:不仅仅是二选一

首先,我们需要纠正一个常见的误区:MQTT 和 WebSocket 并不完全是在同一个层面上的协议。

  • WebSocket 是一种传输协议。它就像一条双向车道,建立连接后,客户端和服务端可以随意互相喊话。但它不管你们聊的内容是什么格式,也不管消息有没有送达,它只负责“传”。
  • MQTT 是一种应用层消息协议。它定义了一套严谨的“快递规则”(发布/订阅模式)。它规定了消息怎么打包、丢了怎么办(QoS)、谁该收这份快递(Topic)。

有趣的事实:MQTT 可以运行在 TCP 之上,也可以运行在 WebSocket 之上(即 MQTT over WebSocket)。


⚔️ 关键差异大比拼

为了让你一目了然,我做了一个核心特性对比表:

维度 WebSocket MQTT
通信模型 点对点 (Client-Server) 发布/订阅 (Pub/Sub)
消息路由 需业务层自己写逻辑处理 基于 Topic (主题) 自动路由
可靠性 依赖 TCP,无应用层确认机制 提供 QoS 0/1/2 三级服务质量
离线消息 需自行实现存储与重推 原生支持保留消息与会会话恢复
带宽消耗 较低 (头部较小) 极低 (固定头部最小仅 2 字节)
浏览器支持 原生支持 (new WebSocket()) 需引入库 (如 mqtt.js)
适用场景 Web聊天、在线协作、自定义协议 IoT设备、大规模消息分发、弱网环境

🧐 什么时候选哪个?
  • 选择 WebSocket,如果…

    • 你的核心场景是 Web 端即时通讯(如网页版微信),且不需要复杂的群组管理。
    • 你需要极高的定制自由度,想自己定义二进制协议格式。
    • 交互主要是“请求-响应”模式的变种,或者是一对一的私密通话。
  • 选择 MQTT,如果…

    • 你在做 IoT(物联网),设备资源受限,网络不稳定(需要 QoS 保活)。
    • 你需要实现复杂的 一对多 分发(例如:一个传感器数据要同时推送到手机App、Web大屏和数据库)。
    • 你希望后端服务解耦,不想自己写复杂的消息路由和广播逻辑。

💻 前端实战:JS 版本接入指南

在浏览器环境中,情况稍微有点特殊:

  • WebSocket:浏览器原生支持,无需安装任何库,直接用 new WebSocket()
  • MQTT:浏览器不支持原生的 TCP 连接,因此我们需要使用 MQTT over WebSocket。这通常需要引入第三方库,最流行的是 mqtt.js
1. WebSocket 前端实现 (原生 JS)

这是最纯粹的 WebSocket 写法,适用于简单的聊天室或实时通知。

<!DOCTYPE html>
<html>
<head><title>WebSocket Demo</title></head>
<body>
    <h2>原生 WebSocket 客户端</h2>
    <div id="status">状态: 未连接</div>
    <input type="text" id="msgInput" placeholder="输入消息" />
    <button onclick="sendMsg()">发送</button>
    <ul id="log"></ul>

    <script>
        // 1. 建立连接 (注意:生产环境通常用 wss://)
        const ws = new WebSocket('ws://localhost:9001');

        // 2. 连接成功
        ws.onopen = () => {
            document.getElementById('status').innerText = '状态: 已连接 ✅';
            addLog('连接到服务器成功');
        };

        // 3. 接收消息
        ws.onmessage = (event) => {
            addLog('收到: ' + event.data);
        };

        // 4. 连接关闭
        ws.onclose = () => {
            document.getElementById('status').innerText = '状态: 已断开 ❌';
            addLog('连接已关闭');
        };

        // 5. 发送消息函数
        function sendMsg() {
            const input = document.getElementById('msgInput');
            if(ws.readyState === WebSocket.OPEN) {
                ws.send(input.value);
                addLog('我说: ' + input.value);
                input.value = '';
            } else {
                alert('连接未开启');
            }
        }

        function addLog(text) {
            const li = document.createElement('li');
            li.innerText = text;
            document.getElementById('log').appendChild(li);
        }
    </script>
</body>
</html>
2. MQTT 前端实现 (使用 mqtt.js)

对于 MQTT,我们需要通过 CDN 引入库,并连接到支持 WebSocket 协议的 MQTT Broker(如 EMQX, Mosquitto 等)。

前置准备:
你需要一个开启了 WebSocket 端口的 MQTT Broker。如果你没有,可以使用公共测试服务器 ws://broker.hivemq.com:8000/mqtt 进行测试。

<!DOCTYPE html>
<html>
<head><title>MQTT.js Demo</title></head>
<body>
    <h2>MQTT.js 客户端</h2>
    <div id="status">状态: 离线</div>
    
    <div>
        <label>主题(Topic): </label>
        <input type="text" id="topic" value="test/topic/1" />
    </div>
    <br>
    <input type="text" id="msgInput" placeholder="输入消息" />
    <button onclick="publish()">发布消息</button>
    <button onclick="subscribe()">订阅主题</button>
    
    <ul id="log"></ul>

    <!-- 引入 mqtt.js 库 -->
    <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>

    <script>
        // 1. 连接配置
        // 注意:浏览器只能用 ws:// 或 wss://,不能用 tcp://
        const options = {
            clientId: 'web_client_' + Math.random().toString(16).substr(2, 8),
            clean: true, // 不保留会话
            connectTimeout: 4000,
            reconnectPeriod: 1000, // 重连间隔
        };

        // 2. 建立连接 (这里使用的是 HiveMQ 的公共测试服务器)
        const client = mqtt.connect('ws://broker.hivemq.com:8000/mqtt', options);

        // 3. 连接成功回调
        client.on('connect', () => {
            document.getElementById('status').innerText = '状态: 已连接到 Broker ✅';
            addLog('MQTT 连接成功!');
        });

        // 4. 接收消息回调
        client.on('message', (topic, message) => {
            addLog(`收到 [${topic}]: ${message.toString()}`);
        });

        // 5. 订阅功能
        function subscribe() {
            const topic = document.getElementById('topic').value;
            client.subscribe(topic, (err) => {
                if (!err) {
                    addLog(`订阅成功: ${topic}`);
                } else {
                    addLog('订阅失败');
                }
            });
        }

        // 6. 发布功能
        function publish() {
            const topic = document.getElementById('topic').value;
            const msg = document.getElementById('msgInput').value;
            
            client.publish(topic, msg, { qos: 1 }, (err) => {
                if(!err) {
                    addLog(`发布成功 [${topic}]: ${msg}`);
                    document.getElementById('msgInput').value = '';
                }
            });
        }

        function addLog(text) {
            const li = document.createElement('li');
            li.innerText = text;
            document.getElementById('log').appendChild(li);
        }
    </script>
</body>
</html>

📝 代码对比小结
特性 WebSocket (原生) MQTT (mqtt.js)
依赖库 无 (浏览器自带) 需引入 mqtt.min.js
连接地址 ws://host:port/path ws://host:port/path (必须是 WS 协议)
核心逻辑 send(), onmessage publish(), subscribe(), on('message')
数据理解 只负责传字符串/二进制 理解 Topic 和 QoS
💻 实战 Demo:手把手教你用

为了演示,我们使用 Python 作为服务端(Broker/Server),分别展示两种协议的实现方式。

前置准备:

# 安装 MQTT 库
pip install paho-mqtt
# 安装 WebSocket 库
pip install websocket-server
场景一:使用 MQTT 实现“发布/订阅”

假设我们要做一个温度监控系统,设备发布温度,多个客户端订阅接收。

服务端(模拟 Broker 逻辑,实际生产推荐用 EMQX 或 Mosquitto):
注:这里主要演示客户端如何交互,通常 MQTT 直接连接现成的 Broker。

发布者 (Publisher) 代码:

import paho.mqtt.client as mqtt
import time

def on_connect(client, userdata, flags, rc):
    print(f"已连接到 Broker,结果: {rc}")
    
client = mqtt.Client()
client.on_connect = on_connect
# 连接本地 Broker (需提前安装 mosquitto 或使用测试服务器)
client.connect("broker.hivemq.com", 1883, 60) 

while True:
    # 向 'home/livingroom/temp' 主题发布消息
    client.publish("home/livingroom/temp", "26.5°C")
    print("发布了温度数据: 26.5°C")
    time.sleep(3)

订阅者 (Subscriber) 代码:

import paho.mqtt.client as mqtt

def on_message(client, userdata, msg):
    print(f"收到消息 [主题: {msg.topic}]: {str(msg.payload)}")

client = mqtt.Client()
client.on_message = on_message
client.connect("broker.hivemq.com", 1883, 60)

# 订阅特定主题
client.subscribe("home/livingroom/temp")
client.loop_forever()
场景二:使用 WebSocket 实现“点对点”聊天

假设我们要做一个简单的回声服务器(Echo Server)。

服务端代码:

from websocket_server import WebsocketServer

def new_client(client, server):
    print(f"新用户连接: {client['id']}")
    server.send_message(client, "欢迎连接到 WebSocket 服务器!")

def message_received(client, server, message):
    print(f"收到消息: {message}")
    # 广播给所有用户
    server.send_message_to_all(f"用户{client['id']}说: {message}")

server = WebsocketServer(port=9001)
server.set_fn_new_client(new_client)
server.set_fn_message_received(message_received)
print("WebSocket 服务器启动中...")
server.run_forever()

客户端代码 (Python):

import websocket

def on_message(ws, message):
    print(f"收到: {message}")

def on_open(ws):
    print("连接已建立,发送消息...")
    ws.send("你好,WebSocket!")

ws = websocket.WebSocket()
ws.connect("ws://localhost:9001")
on_open(ws)

# 保持接收
while True:
    msg = ws.recv()
    on_message(ws, msg)

🏆 总结与建议

在实际的企业级开发中,现在的趋势往往是 “混合双打”

  • 设备端 -> 云端:使用 MQTT,保证弱网下的可靠传输和设备状态管理。
  • 云端 -> Web/App:使用 MQTT over WebSocket 或者直接封装一层 WebSocket

如果你的项目刚开始,规模不大,且主要在浏览器上跑,直接用 WebSocket 最快;如果你面对的是成千上万的传感器或复杂的推送需求,请务必拥抱 MQTT。

希望这篇文章能帮你在技术选型时少走弯路!如果觉得有用,欢迎点赞收藏关注!👋

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐