CocoaMQTT v2.0:首个支持 MQTT 5.0 的 iOS 客户端
2017 年 8 月,OASIS MQTT Technical Committee 正式發布了用于 Public Review 的 MQTT 5.0 的草案。2018 年,MQTT 5.0 正式發布,然而直到目前蘋果生態里仍沒有完整支持 MQTT 5.0 的客戶端 SDK 。
CocoaMQTT 是 EMQ 團隊為 iOS 開發者提供的 MQTT 客戶端 SDK,目前在 iOS 開發者中有著較為廣泛的使用。
為彌補蘋果生態中對 MQTT 5.0 支持方面的空白,EMQ 團隊于近日正式發布了 CocoaMQTT 全新版本 v2.0。CocoaMQTT v2.0 支持 MQTT 5.0,同時兼容 3.1.1 版本,支持 iOS、tvOS 與 OSX 操作系統。用戶現已可通過 CocoaMQTT 實現 iOS 系統設備連接 MQTT 5.0 云服務,享受 MQTT 5.0 帶來的強大功能加成。
CocoaMQTT 使用 Swift 語言開發,而非 Objective-C。這是因為 Swift 是一門類型安全的語言,對協議的支持更加豐富,配合擴展(extension)、泛型、關聯類型等可以實現面向協議編程,從而大大提高代碼的靈活性。
此外,在 WWDC 2021 大會上,蘋果宣布了 Swift 語言中并發模型的重大更新:通過編譯器實現的 Actor 并發模型,新增 Actor 引用類型幫助開發者避免數據競爭問題。
因此,我們相信在 MQTT 相關的 I/O 密集型并發應用中,相較于 Objective-C,Swift 的表現將更值得期待。
MQTT 5.0 vs MQTT 3.1.1
MQTT 3.1.1 仍然有很多不完善的地方,例如連接異常斷開時無法通知原因到對端。MQTT 5.0 在 MQTT 3.1.1 的基礎上做了很多改變,但并不是向下兼容的。
MQTT 協議 5.0 版本新增了會話/消息延時功能、原因碼、主題別名、in-flight 流控、用戶屬性、共享訂閱等功能,以及用于增強認證安全的 AUTH 報文。其中,原因碼和用戶屬性 Property 字段使得 MQTT 5.0 能夠攜帶更多上下文信息,從而解決在 3.1.1 版本因協議不完整而較難處理的問題。
MQTT 5.0 的主要功能優勢有:
- 進一步支持更大規模的可擴展系統
- 更加詳細的錯誤報告和處理機制
- 容量探索和請求響應等通用模式的規范化操作
- 可擴展的用戶屬性 (User Property)
- 改進性能并支持小型客戶端
- 會話保持和消息超時設置
- 新增支持 Req/Rsp 消息模式
CocoaMQTT 客戶端的使用
本文將使用 EMQ 提供的 免費公共 MQTT 服務器 進行 CocoaMQTT 功能使用介紹,該服務基于 MQTT 云服務 EMQ X Cloud 創建。
服務器接入信息如下:
- Broker: broker-cn.emqx.io
- TCP Port: 1883
- Websocket Port: 8083
- TCP/TLS 端口: 8883
- Websocket/TLS 端口:8084
連接 MQTT 服務
我們看到 MQTT 5.0 增加了許多屬性,其中 Property 字段可以讓使用者根據自己的情況,更加細致化去完成需求。
///MQTT 5.0 let clientID = "CocoaMQTT-" + String(ProcessInfo().processIdentifier) let mqtt5 = CocoaMQTT5(clientID: clientID, host: "broker-cn.emqx.io", port: 1883)let connectProperties = MqttConnectProperties() connectProperties.topicAliasMaximum = 0 connectProperties.sessionExpiryInterval = 0 connectProperties.receiveMaximum = 100 connectProperties.maximumPacketSize = 500 mqtt5.connectProperties = connectPropertiesmqtt5.username = "test" mqtt5.password = "public" mqtt5.willMessage = CocoaMQTTWill(topic: "/will", message: "dieout") mqtt5.keepAlive = 60 mqtt5.delegate = self mqtt5.connect()///MQTT 3.1.1 let clientID = "CocoaMQTT-" + String(ProcessInfo().processIdentifier) let mqtt = CocoaMQTT(clientID: clientID, host: "broker-cn.emqx.io", port: 1883) mqtt.username = "test" mqtt.password = "public" mqtt.willMessage = CocoaMQTTWill(topic: "/will", message: "dieout") mqtt.keepAlive = 60 mqtt.delegate = self mqtt.connect()訂閱主題
MQTT 5.0 在 MQTT 3.1.1 上面多了訂閱選項等操作。
///MQTT 5.0 mqtt5.subscribe("chat/room/animals/client/+", qos: CocoaMQTTQoS.qos1) //or //let subscriptions : [MqttSubscription] = [MqttSubscription(topic: "chat/room/animals/client/+"),MqttSubscription(topic: "chat/room/foods/client/+"),MqttSubscription(topic: "chat/room/trees/client/+")] //mqtt.subscribe(subscriptions)///MQTT 3.1.1 mqtt.subscribe("chat/room/animals/client/+", qos: CocoaMQTTQoS.qos1) //or //let subscriptions : [(String, CocoaMQTTQoS)] = [("chat/room/animals/client/+", qos: CocoaMQTTQoS.qos1),("chat/room/foods/client/+", qos: CocoaMQTTQoS.qos1),("chat/room/trees/client/+", qos: CocoaMQTTQoS.qos1)] //mqtt.subscribe(subscriptions)發布消息
///MQTT 5.0 mqtt5!.publish("chat/room/animals/client/" + animal!, withString: message!, qos: .qos1, DUP: false, retained: false, properties: publishProperties)///MQTT 3.1.1 mqtt!.publish("chat/room/animals/client/" + animal!, withString: message!, qos: .qos1)自動重連
MQTT 是基于 TCP 長連接的協議,在實際使用的場景中,由于網絡故障或信號問題導致連接中斷是經常出現的問題。許多開發者會希望 SDK 能夠提供方便的自動重連方式。
///MQTT 5.0 mqtt5!.autoReconnect = true///MQTT 3.1.1 mqtt!.autoReconnect = true單雙向 SSL 連接
///MQTT 5.0 mqtt5!.enableSSL = true///MQTT 3.1.1 mqtt!.enableSSL = truelet clientCertArray = getClientCertFromP12File(certName: "client-keycert", certPassword: "MySecretPassword") var sslSettings: [String: NSObject] = [:] sslSettings[kCFStreamSSLCertificates as String] = clientCertArray///MQTT 5.0 mqtt5!.sslSettings = sslSettings///MQTT 3.1.1 mqtt!.sslSettings = sslSettings如果需要 .p12 文件可以在終端使用以下語句生成。
1openssl pkcs12 -export -clcerts -in client-cert.pem -inkey client-key.pem -out client.p12設置保留消息和遺囑消息
MQTT 5.0 與 MQTT 3.1.1 比,多了更多的屬性設置可供用戶使用。
///MQTT 5.0 let lastWillMessage = CocoaMQTTMessage(topic: "/chat/room/animals/client/Sheep", string: "dieout") lastWillMessage.retained = true lastWillMessage.qos = .qos1 mqtt5!.willMessage = lastWillMessage///MQTT 3.1.1 mqtt!.willMessage = CocoaMQTTMessage(topic: "/will", string: "dieout")AUTH 報文
MQTT 單純通過 CONNECT 可能無法提供足夠的信息給 Server 進行身份認證,所以 MQTT 5.0 新增此功能。用于客戶端和服務器之間的加強認證。
let authProperties = MqttAuthProperties()mqtt5!.auth(reasonCode: CocoaMQTTAUTHReasonCode.continueAuthentication, authProperties: authProperties)iOS 應用后臺運行
推薦使用 「Background fetch」模式或 IOS 13 新增的「Background processing」模式。
如果使用 beginBackgroundTaskWithName 和 endBackgroundTask 相關的 API,可以保持 APP 在后臺運行 30 秒。
總結
至此,我們完成了使用 CocoaMQTT 客戶端連接到公共 MQTT 服務器,并實現了客戶端與 MQTT 服務器的連接、消息發布和訂閱。
項目完整代碼請見 https://github.com/emqx/CocoaMQTT/tree/master/Example。
EMQ 致力于幫助用戶輕松便捷地使用 MQTT 開展物聯網業務,我們的一系列客戶端 SDK 均在持續開發中,敬請關注。
版權聲明: 本文為 EMQ 原創,轉載請注明出處。
原文鏈接:https://www.emqx.com/zh/blog/ios-mqtt5-client
技術支持:如對本文或 EMQ 相關產品有疑問,可訪問 EMQ 問答社區 https://askemq.com 提問,我們將會及時回復支持。
更多技術干貨,歡迎關注我們公眾號【EMQ 中文社區】。
總結
以上是生活随笔為你收集整理的CocoaMQTT v2.0:首个支持 MQTT 5.0 的 iOS 客户端的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: liferay mysql_Lifera
- 下一篇: 面向对象程序设计实践(C++)——二维向