日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

iOS中MQTT和WS的简单混合使用

發布時間:2024/3/24 c/c++ 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS中MQTT和WS的简单混合使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? ? ?歷經三天的尋找和嘗試,終于完成了一個任務,任務要求的服務器訪問用WebSocket的URL格式的,而訪問結束后要進行訂閱和消息發送,這更多出現在MQTT協議的框架里,例如這個文章

https://www.jianshu.com/p/80ea4507ca74? ?《iOS MQTT----MQTTClient實戰-看這篇的就夠了》。但是這個文章的框架訪問示例代碼的host和端口port設置的方式如下:

-(void)loginMQTT{/*設置ip和端口號*/self.transport.host=_ip;self.transport.port=_port;/*設置MQTT賬號和密碼*/self.mqttSession.transport=self.transport;//給MQTTSession對象設置基本信息self.mqttSession.delegate=self;//設置代理[self.mqttSession setUserName:_userName];[self.mqttSession setPassword:_password];//會話鏈接并設置超時時間[self.mqttSession connectAndWaitTimeout:5]; }

該方式的host格式嚴格是“xxx.xxx.xx.xx”,如果格式錯誤,會直接訪問報錯,域名解析錯誤。報錯信息如下:

2021-05-27 09:49:58.630527+0800 Intelligent_fire_protection[28024:9675835] Error Domain=kCFErrorDomainCFNetwork Code=2 "(null)" UserInfo={_kCFStreamErrorDomainKey=12, _kCFStreamErrorCodeKey=8, kCFGetAddrInfoFailureKey=8}

有時也會返回404,報錯信息如下

Error Domain=SRWebSocketErrorDomain Code=2132 "received bad response code from server 404" UserInfo={NSLocalizedDescription=received bad response code from server 404, HTTPResponseStatusCode=404}

如果格式包含了path,例如“ws://xxxx/xxxx.xx.xx/mqtt”,需要將? ? self.transport.host=_ip;和self.transport.port=_port;刪去,改成self.transport.url=“ws://xxxx/xxxx.xx.xx/mqtt”。

實現效果我沒具體實踐,應該不會有問題,起初我沒發現這個url屬性,host地址又被框架定死沒辦法和后臺統一,訪問又一直失敗,于是我換了一個網上的demo,在另一個demo里發現了url屬性,并完成了我的需求,后來回頭查看這個框架的時候,發現也有url屬性。爬坑了。

?

接下來我簡單介紹一下我應用的這個框架:

? ? ? ?該框架引用來自:https://blog.csdn.net/sinat_23907467/article/details/84840699,《iOS MQTT 簡單使用流程》

? ? ? ?配置MQTT。?MQTTClient 配置更多 是可持續更新,可配置 SSL

pod 'MQTTClient' pod 'MQTTClient/MinL' pod 'MQTTClient/ManagerL' pod 'MQTTClient/WebsocketL'

? ? ? ?.h文件中添加文件頭和MQTTsession變量

#import <MQTTClient.h> #import <MQTTWebsocketTransport.h> #define WEAKSELF __typeof(&*self) __weak weakSelf = self;@property (nonatomic, strong) MQTTSession *mySession;

? ? ?.m文件中添加協議<MQTTSessionDelegate,MQTTSessionManagerDelegate>,定義相應的變量,本文后續代碼都在改.m文件中添加

@property(nonatomic,strong)NSString *server_ip; @property(nonatomic,strong)NSString *userName; @property(nonatomic,strong)NSString *passWord; @property(nonatomic,strong)NSArray *topics;

文章中用到了下面的代碼,但我在應用時候鏈接服務器報錯了,我便把這部分代碼注釋掉了,實際上這部分代碼只是避免持續等待連接卡死的情況,當連接時間超過某一個時間長度就強制斷開申請連接。后文中我另加了一行代碼實現這個功能。

MQTTCFSocketTransport *transport = [[MQTTCFSocketTransport alloc] init];transport.host = @"localhost";transport.port = 1883;MQTTSession *session = [[MQTTSession alloc] init];session.transport = transport;session.delegate = self;[session connectAndWaitTimeout:30];

WebSocket的初始化和鏈接代碼:

引用的文章中用的是host和port,但這個不符合web的地址格式,往往web會有一個path路徑,所以訪問會報錯,錯誤代碼是5,MQTTSessionEventConnectionClosedByBroker。所以還需要在代碼中添加一行transport.path=@"ws";或者將post和port兩行注釋掉,直接手動輸入一個url 即 NSURL *url=[NSURL URLWithString:_server_ip];? transport.url=url;? ?其中_server_ip的格式為“ws://xxxx.xxxx.xx.xx/ws”

另外,上文中我注釋掉的代碼在此處實現了,即? [session connectAndWaitTimeout:10];

引用的文章中有個 [self reconnect];代碼,實際是重新連接功能,實際使用時候文章沒提供,已經沒有這個函數了,所以我用的[self.mySession connect];代替。

WEAKSELF // NSString *myId=[NSString stringWithFormat:@"%d",arc4random()%10000];NSString *clientID =[NSString stringWithFormat:@"%@|iOS|%@",[[NSBundle mainBundle] bundleIdentifier],[UIDevice currentDevice].identifierForVendor.UUIDString];;MQTTWebsocketTransport *transport = [[MQTTWebsocketTransport alloc] init]; // transport.host = [NSString stringWithFormat:@"%@",server_ip]; // transport.port = 9999; // 端口號NSURL *url=[NSURL URLWithString:_server_ip];transport.url=url; // transport.path=@"ws";transport.tls = YES; // 根據需要配置 YES 開起 SSL 驗證 此處為單向驗證 雙向驗證 根據SDK 提供方法直接添加MQTTSession *session = [[MQTTSession alloc] init];NSString *linkUserName = _userName;NSString *linkPassWord = _passWord;[session setUserName:linkUserName];[session setClientId:clientID];[session setPassword:linkPassWord];[session setKeepAliveInterval:5];session.transport = transport;session.delegate = self;[session connectAndWaitTimeout:10];self.mySession = session;[self.mySession connect];//self reconnect[self.mySession addObserver:self forKeyPath:@"state" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil]; //添加事件監聽

WebSocket 監聽,響應事件:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {switch (self.mySession.status) {case MQTTSessionManagerStateClosed:NSLog(@"連接已經關閉");break;case MQTTSessionManagerStateClosing:NSLog(@"連接正在關閉");break;case MQTTSessionManagerStateConnected:NSLog(@"已經連接");break;case MQTTSessionManagerStateConnecting:NSLog(@"正在連接中");break;case MQTTSessionManagerStateError: {// NSString *errorCode = self.mySession.lastErrorCode.localizedDescription;NSString *errorCode = self.mySession.description;NSLog(@"連接異常 ----- %@",errorCode);}break;case MQTTSessionManagerStateStarting:NSLog(@"開始連接");break;default:break;} }

session Delegate 協議

連接 返回狀態

根據我的項目需求,我直接在訂閱成功后直接對topic進行了訂閱,即代碼中for循環,讀者可以自行更改訂閱邏輯。

-(void)handleEvent:(MQTTSession *)session event:(MQTTSessionEvent)eventCode error:(NSError *)error{if (eventCode == MQTTSessionEventConnected) {NSLog(@"鏈接MQTT 成功");// 方法 封裝 可外部調用for (NSString *topic in _topics) {[session subscribeToTopic:topic atLevel:2 subscribeHandler:^(NSError *error, NSArray<NSNumber *> *gQoss){if (error) {NSLog(@"Subscription failed %@", error.localizedDescription);} else {NSLog(@"Subscription sucessfull! Granted Qos: %@", gQoss);// [self send];}}];}// this is part of the block API}else if (eventCode == MQTTSessionEventConnectionRefused) {NSLog(@"MQTT拒絕鏈接");}else if (eventCode == MQTTSessionEventConnectionClosed){NSLog(@"MQTT鏈接關閉");}else if (eventCode == MQTTSessionEventConnectionError){NSLog(@"MQTT 鏈接錯誤");}else if (eventCode == MQTTSessionEventProtocolError){NSLog(@"MQTT 不可接受的協議");}else{//MQTTSessionEventConnectionClosedByBrokerNSLog(@"MQTT鏈接 其他錯誤");}if (error) {NSLog(@"鏈接報錯 -- %@",error);} }

收到來自服務器的信息,并對改信息進行相應處理

-(void)newMessage:(MQTTSession *)session data:(NSData *)data onTopic:(NSString *)topic qos:(MQTTQosLevel)qos retained:(BOOL)retained mid:(unsigned int)mid {NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; // NSLog(@"EasyMqttService mqtt connect success %@",dic);// 做相對應的操作 }

取消訂閱,斷開與服務器的鏈接:

-(void)closeMQTTClient{[self.mySession disconnect];[self.mySession unsubscribeTopics:@[@"已經訂閱的主題"] unsubscribeHandler:^(NSError *error) {if (error) {NSLog(@"取消訂閱失敗");}else{NSLog(@"取消訂閱成功");}}]; }

以下內容是我封裝了該框架,并留了三個方法用于鏈接,發送數據和斷開連接。讀者自行在.h文件中添加對應的方法:

-(void)connectServer:(NSString *)urlString userName:(NSString *)userName passWord:(NSString *)passWord topic:(NSArray *)topics{_server_ip=urlString;_userName=userName;_passWord=passWord;_topics=topics;[self websocket];} -(void)disConnectServer{[_mySession closeAndWait:1];self.mySession.delegate=nil;//代理_mySession=nil; // _transport=nil;//連接服務器屬性_server_ip=nil;//服務器ip地址 // _port=0;//服務器ip地址_userName=nil;//用戶名_passWord=nil;//密碼 // _topic=nil;//單個主題訂閱_topics=nil;//多個主題訂閱 } -(void)sendMassage:(NSData *)msg topic:(NSString *)topic{[self.mySession publishData:msg onTopic:topic retain:NO qos:MQTTQosLevelExactlyOnce publishHandler:^(NSError *error) {if (error) {NSLog(@"發送失敗 - %@",error);}else{NSLog(@"發送成功");}}]; }

?

總結

以上是生活随笔為你收集整理的iOS中MQTT和WS的简单混合使用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。