柚子快報激活碼778899分享:Qt與MQTT交互通信
柚子快報激活碼778899分享:Qt與MQTT交互通信
MQTT全稱是(Message Queuing Telemetry Transport),即消息隊列遙測傳輸協(xié)議
是一種基于發(fā)布/訂閱(Publish/Subscribe)模式的輕量級通訊協(xié)議,并且該協(xié)議構(gòu)建于TCP/IP協(xié)議之上,常用于互聯(lián)網(wǎng)中,輕便
基本組件
客戶端(Client):
任何設(shè)備(傳感器、手機、應(yīng)用程序等)都可以作為MQTT客戶端??蛻舳丝梢园l(fā)布消息(Publisher)或者訂閱消息(Subscriber)。 代理(Broker):
代理是MQTT網(wǎng)絡(luò)的核心組件,負(fù)責(zé)接收來自發(fā)布者的消息并將其轉(zhuǎn)發(fā)給訂閱了該主題的客戶端。它確保消息的傳遞和分發(fā),管理客戶端連接、訂閱、注銷等操作。
工作流程
連接:
MQTT客戶端通過TCP/IP與MQTT代理建立連接。連接建立后,客戶端必須發(fā)送“連接”請求。代理根據(jù)請求的信息(如客戶端ID、用戶名、密碼等)進(jìn)行身份驗證和授權(quán)。 發(fā)布(Publish):
客戶端將消息發(fā)布到特定的主題(Topic)。主題是一種類似路徑的層級結(jié)構(gòu),可以用斜杠(/)分隔,如?sensors/temperature/kitchen。代理接收消息并進(jìn)行處理。 訂閱(Subscribe):
客戶端可以訂閱一個或多個主題。訂閱后,代理會將所有屬于該主題的消息分發(fā)給相應(yīng)的客戶端。訂閱可以是精確的主題,也可以包含通配符來匹配多個主題。 消息分發(fā):
代理將發(fā)布的消息轉(zhuǎn)發(fā)給所有訂閱了該主題的客戶端。 斷開連接:
客戶端可以隨時斷開與代理的連接。代理也可以在檢測到長時間未活動后斷開客戶端連接。
應(yīng)用場景
MQTT廣泛應(yīng)用于物聯(lián)網(wǎng)、車聯(lián)網(wǎng)、智能家居、遠(yuǎn)程監(jiān)控和消息推送等場景。其輕量級、低帶寬、高效的特性使其特別適合資源受限及網(wǎng)絡(luò)不穩(wěn)定的環(huán)境。
通過這些組件和操作,MQTT可以實現(xiàn)高效、可靠的消息傳遞,成為物聯(lián)網(wǎng)通信中的重要協(xié)議。
QT 交互例子
準(zhǔn)備工作:MQTT客戶端的交互需要安裝MQTT代理,及代理服務(wù)器,負(fù)責(zé)將消息轉(zhuǎn)發(fā)。按照好后配置相關(guān),如監(jiān)聽的端口和協(xié)議、是否啟用消息持久化、日志文件路徑等。根據(jù)需求修改這些設(shè)置,保存配置文件等。這里就不贅述
接下來詳細(xì)講解在QT中MQTT的使用:
1.使用官方的MQTT源碼,造好的輪子有用就用,官網(wǎng):https://github.com/emqx/qmqtt
或者這個鏈接下載: https://pan.baidu.com/s/1oUtl9R628-3cfS-tyL6iEQ?pwd=1234 提取碼: 1234?
下載完解壓:放到程序目錄下
我的例子程序結(jié)構(gòu)如下,分為mqtt封裝的庫,用于發(fā)送接收消息,和界面主程序用于控制發(fā)送和消息顯示
2.寫一個例子,這里給關(guān)鍵代碼展示
一是連接mqtt,二是推送消息函數(shù),三是接收訂閱的消息函數(shù)
void MqttShareHandle::initMqtt()
{
if (client) {
return;
}
client.reset(new QMqttClient);
QObject::connect(client.get(), &QMqttClient::connected, this, &MqttShareHandle::connected);
QObject::connect(client.get(), &QMqttClient::disconnected, this, &MqttShareHandle::disconnected);
QObject::connect(client.get(), &QMqttClient::errorChanged, this, &MqttShareHandle::errorChanged);
QObject::connect(client.get(), &QMqttClient::messageReceived, this,
[=](const QByteArray &message, const QMqttTopicName &topic) {
emit messageReceived(message, topic.name());
});
QObject::connect(client.get(), &QMqttClient::messageReceived, this,
[=](const QByteArray &message, const QMqttTopicName &topic) {
onMessageReceived(message, topic.name());
});
}
void MqttShareHandle::connectToHost(const QString &host,
quint16 port,
const QString &username,
const QString &password)
{
if (!client || isConnected()) {
return;
}
client->setHostname(host);
client->setPort(port);
client->setUsername(username);
client->setPassword(password);
client->connectToHost();
}
//訂閱消息
void MqttShareHandle::subscribeBizTopics()
{
//保證消息至少到達(dá)一次。
//較為可靠,適用于大多數(shù)需要保證消息到達(dá)的場景
const quint8 qos = 1;
subscribeTopic(TopicAppEnvData, qos);
subscribeTopic(TopicAppDeviceStatus, qos);
subscribeTopic(TopicAppEventNotify, qos);
}
bool MqttShareHandle::subscribeTopic(const QString &topic, quint8 qos)
{
if (!client) {
return false;
}
auto subscription = client->subscribe(topic, qos);
return subscription ? subscription->state() == QMqttSubscription::Subscribed : false;
}
//推送消息
bool MqttShareHandle::publishTopic(const QString &topic, const QByteArray &data, quint8 qos, bool retain)
{
if (!client) {
return false;
}
emit printMsg(QString("推送消息, topic:%1,data:%2").arg(topic).arg(QString(data)));
auto ret = client->publish(topic, data, qos, retain);
return ret != -1;
}
void MqttShareHandle::onMessageReceived(const QByteArray &message, const QString &topic)
{
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(message, &error);
if (error.error != QJsonParseError::NoError) {
return;
}
//QMetaObject::invokeMethod(this, MessageMap.value(topic).toUtf8(), Q_ARG(QByteArray,message));
emit printMsg(QString("收到消息推送, topic:%1,data:%2").arg(topic).arg(QString(message)));
if(topic == TopicAppEnvData) {
emit appEnvDataUpdate(message);
}
else if(topic == TopicAppEventNotify) {
emit appEventNotify(message);
}
else if(topic == TopicAppDeviceStatus) {
emit appDeviceStatusUpdate(message);
}
}
我的這個例子用了五個主題要演示推送和接收
// 環(huán)境信息更新主題
QString MqttShareHandle::TopicAppEnvData = "/Topic/EnvData";
// 設(shè)備狀態(tài)更新主題
QString MqttShareHandle::TopicAppDeviceStatus = "/Topic/DeviceStatus";
// 事件通知主題
QString MqttShareHandle::TopicAppEventNotify = "/Topic/EventNotify";
//------------------------消息發(fā)布(推送)-------------------------
// 控制設(shè)備主題
QString MqttShareHandle::TopicControlDevice = "/Topic/ControlDevice";
// 控制門主題(開關(guān)門)
QString MqttShareHandle::TopicControlDoor = "/Topic/ControlDoor";
寫了一個demo程序,如下,改程序可以通過mqtt推送開關(guān)門控制事件,模擬控制訂閱“TopicControlDoor”主題的設(shè)備控制開關(guān)門,控制訂閱TopicControlDevice主題的設(shè)備控制開關(guān)燈,并且訂閱相關(guān)設(shè)備推送消息的主題,便于接收響應(yīng)的信息
演示下效果,比較簡陋,:
我用這個QT客戶端模式外部設(shè)備
演示視頻
通過訂閱環(huán)境主題,事件,設(shè)備狀態(tài),可以接收設(shè)備的相關(guān)消息推送
設(shè)備也訂閱了控門事件,控?zé)羰录?。接收到app的推送后,也顯示出來,做出相應(yīng)的處理
通過這個例子,可以認(rèn)識到,mqtt的通訊方式是一對多,也可以一對一,實現(xiàn)方式也很簡單,訂閱與發(fā)布。
訂閱就相當(dāng)于你關(guān)注了一個人,UP主(uploader),他要是發(fā)布了動態(tài)或者視頻等,就會通知你,如果你沒有關(guān)注那個人,肯定不會接收到通知
發(fā)布就反過來,你是UP主,發(fā)布的東西只要他人關(guān)注了你,就會被通知
這個例子的源碼我就放在這里了,有什么不懂的,歡迎評論區(qū)交流哈!
鏈接: https://pan.baidu.com/s/1v_xViXSHoV2QekwdKDq7SA?pwd=6666 提取碼: 6666?
為什么有了tcp通信后,還要有人寫一個mqtt出來呢?
mqtt的優(yōu)勢
1.?發(fā)布/訂閱模式
MQTT 采用發(fā)布/訂閱模式,允許客戶端發(fā)布消息到主題(Topic),其他客戶端可以訂閱這些主題來接收消息。這種模式使得消息的傳遞更加靈活和解耦,客戶端之間不需要直接連接,減少了復(fù)雜性。
2.?輕量級
MQTT 協(xié)議設(shè)計得非常輕量級,適合在帶寬有限、網(wǎng)絡(luò)不穩(wěn)定的環(huán)境中使用,如物聯(lián)網(wǎng)設(shè)備。MQTT 的消息頭非常小,最小只有 2 字節(jié),這使得它在低帶寬網(wǎng)絡(luò)中傳輸效率更高。
3.?QoS(服務(wù)質(zhì)量)
MQTT 提供了三種服務(wù)質(zhì)量(QoS)級別:
QoS 0:最多一次(At most once),消息發(fā)送一次,不保證接收。QoS 1:至少一次(At least once),消息至少發(fā)送一次,可能會重復(fù)。QoS 2:恰好一次(Exactly once),消息只發(fā)送一次,保證不重復(fù)。
QoS 0(最多一次,At most once)
特點:
消息傳輸是盡力而為,不保證消息到達(dá)。不進(jìn)行消息確認(rèn),不做重發(fā)。最低的網(wǎng)絡(luò)開銷和延遲。
使用場合:
傳感器數(shù)據(jù):如環(huán)境溫度、濕度等,定期發(fā)送,如果丟失一兩條數(shù)據(jù)不會有太大影響。日志數(shù)據(jù):實時性和完整性要求不高的日志信息。狀態(tài)更新:如設(shè)備的在線狀態(tài),定期發(fā)送,如果有丟失可在下次更新時彌補。
優(yōu)點:
最低的網(wǎng)絡(luò)開銷。最低的延遲。簡單實現(xiàn)。
缺點:
不保證消息到達(dá)??赡軙G失消息。
QoS 1(至少一次,At least once)
特點:
消息至少到達(dá)一次。發(fā)送者會重發(fā)消息直到收到接收者的確認(rèn)。接收者可能會收到重復(fù)的消息,需要去重。
使用場合:
重要數(shù)據(jù):如報警信息,需要確保接收者至少收到一次,即使可能會有重復(fù)。財務(wù)記錄:如銀行交易,需要確保消息到達(dá),但可以接受重復(fù)處理。設(shè)備控制:如遠(yuǎn)程設(shè)備控制命令,需要確保命令被接收和執(zhí)行,但可以手動處理重復(fù)執(zhí)行。
優(yōu)點:
保證消息至少到達(dá)一次。較為可靠,適用于大多數(shù)需要保證消息到達(dá)的場景。
缺點:
可能會收到重復(fù)消息,需要處理冗余。網(wǎng)絡(luò)開銷和延遲高于 QoS 0。
QoS 2(只有一次,Exactly once)
特點:
消息保證到達(dá)且僅到達(dá)一次。通過四次消息交換確保消息的唯一性和可靠性。最高的可靠性,適合對傳輸可靠性要求極高的場合。
使用場合:
關(guān)鍵指令:如關(guān)鍵操作的執(zhí)行命令,不能出現(xiàn)丟失或重復(fù)的情況。交易處理:如金融交易,需要嚴(yán)格的消息確保機制,要求高可靠性。數(shù)據(jù)同步:如重要數(shù)據(jù)庫的同步操作,需要確保數(shù)據(jù)準(zhǔn)確性和一致性。
優(yōu)點:
保證消息僅到達(dá)一次。最高的傳輸可靠性。
缺點:
最高的網(wǎng)絡(luò)開銷。延遲較高,因為需要多次消息交換。實現(xiàn)復(fù)雜。
這些 QoS 級別使得 MQTT 能夠適應(yīng)不同的應(yīng)用場景,確保消息的可靠傳輸。
4.?會話保持
MQTT 支持會話保持(Session Persistence),即使在客戶端斷開連接后,服務(wù)器仍然可以保存客戶端的訂閱信息和未接收的消息,當(dāng)客戶端重新連接時,可以繼續(xù)接收這些消息。
5.?遺囑消息(Last Will and Testament)
MQTT 支持遺囑消息(LWT),客戶端可以在連接時設(shè)置一個遺囑消息,當(dāng)客戶端異常斷開連接時,服務(wù)器會自動發(fā)布這個遺囑消息,通知其他客戶端該客戶端已經(jīng)斷開連接。
6.?心跳機制
MQTT 支持心跳機制(Keep Alive),客戶端可以定期發(fā)送 PING 請求,確保連接的活躍性,服務(wù)器也可以通過 PING 響應(yīng)來檢測客戶端的連接狀態(tài)。
7.?安全性
MQTT 支持 TLS/SSL 加密,確保消息在傳輸過程中的安全性。此外,MQTT 還支持用戶名和密碼認(rèn)證,增加了系統(tǒng)的安全性。
8.?易于擴展
MQTT 的發(fā)布/訂閱模式和主題(Topic)結(jié)構(gòu)使得系統(tǒng)易于擴展。新的客戶端可以輕松地加入系統(tǒng),訂閱感興趣的主題,而不需要修改現(xiàn)有的客戶端或服務(wù)器。
9.?廣泛支持
MQTT 協(xié)議得到了廣泛的支持,有大量的客戶端庫和服務(wù)器實現(xiàn),適用于各種編程語言和平臺,如 C、C++、Java、Python、JavaScript 等。
總結(jié)
相比于直接使用 TCP,MQTT 提供了更高層次的抽象和功能,使得消息的傳遞更加靈活、可靠和高效。特別是在物聯(lián)網(wǎng)和低帶寬網(wǎng)絡(luò)環(huán)境中,MQTT 的優(yōu)勢更加明顯。
柚子快報激活碼778899分享:Qt與MQTT交互通信
參考鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。