====== 快速使用MQTT iOS版 SDK实现消息收发 ====== 本文介绍快速使用 MQTT iOS版SDK 实现MQTT客户端消息的自收自发。 =====1. 前提条件===== ==== 1.1 部署iOS开发环境 ==== * 下载安装[[https://developer.apple.com/cn/support/xcode|xcode]]。 * 下载安装[[https://www.jianshu.com/p/fb7f533c39fc|cocoapods]],本文以cocoapods为例。 ==== 1.2 导入项目依赖 ==== 在项目的podfile文件中设置如下: source 'https://github.com/CocoaPods/Specs.git' platform :ios, '10.0' pod 'MQTTClient' pod 'AFNetworking' pod 'MBProgressHUD' pod 'Masonry' pod 'MJRefresh' pod 'YYModel' target 'MQTTChat' do end ===== 2. 实现流程 ===== ==== 2.1 获取初始化信息 ==== 登录console后台 \\ 1.点击菜单栏【MQTT】->【服务概览】->【服务配置】,获取「连接地址」、「连接端口」、「AppID」以「及REST API地址」等信息。 \\ 注:clientID由两部分组成,组织形式为“deviceID@AppID”,deviceID由用户自定义,AppID见【服务配置】。 \\ 示例:正确的clientID格式为:“device001@aitbj0”; \\ 2.点击菜单栏【应用概览】->【应用详情】->【开发者ID】,获取「Client ID」与「ClientSecret」信息。 \\ 3.初始化代码 self.rootTopic = @"t1"; // appID 通过console后台[MQTT]->[服务概览]->[服务配置]下[AppID]获取 self.appId = @"ff6sc0"; //环信MQTT服务器地址 通过console后台[MQTT]->[服务概览]->[服务配置]下[连接地址]获取 self.host = @"ff6sc0.cn1.mqtt.chat"; //环信MQTT REST API地址 通过console后台[MQTT]->[服务概览]->[服务配置]下[REST API地址]获取 self.restapi = @"https://api.cn1.mqtt.chat/app/ff6sc0"; //开发者ID 通过console后台[应用概览]->[应用详情]->[开发者ID]下[ Client ID]获取 self.appClientId = @"YXA67-uKaalmThCOut6Q8uPLSg"; // 开发者密钥 通过console后台[应用概览]->[应用详情]->[开发者ID]下[ ClientSecret]获取 self.appClientSecret = @"YXA63CFpMQFai4MdTDdGN92BBoG6_6g"; // 协议服务端口 通过console后台[MQTT]->[服务概览]->[服务配置]下[连接端口]获取 self.port = 1883; self.qos = 0; self.tls = 0; // 自定义deviceID self.deviceId = [UIDevice currentDevice].identifierForVendor.UUIDString; //开发者ID 通过console后台[应用概览]->[应用详情]->[开发者ID]下[ Client ID]获取 self.clientId = [NSString stringWithFormat:@"%@@%@",self.deviceId,self.appId]; {{:playground:message:setting.jpg|}} {{:playground:message:develop.jpg|}} ==== 2.2 获取token ==== //获取应用token - (void)getAppTokenWithAppClientId:(NSString *)appClientId appClientSecret:(NSString *)appClientSecret completion:(void (^)(NSString *appToken,NSInteger expires))response { //环信MQTT REST API地址 通过console后台[MQTT]->[服务概览]->[服务配置]下[REST API地址]获取 NSString *urlString = [NSString stringWithFormat:@"%@/openapi/rm/app/token",self.restapi]; //初始化一个AFHTTPSessionManager AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; //设置请求体数据为json类型 manager.requestSerializer = [AFJSONRequestSerializer serializer]; //设置响应体数据为json类型 manager.responseSerializer = [AFJSONResponseSerializer serializer]; //请求体,参数(NSDictionary 类型) NSDictionary *parameters = @{@"appClientId":appClientId, @"appClientSecret":appClientSecret }; __block NSString *token = @""; [manager POST:urlString parameters:parameters headers:@{} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSError *error = nil; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:responseObject options:NSJSONWritingPrettyPrinted error:&error]; NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error]; NSLog(@"%s jsonDic:%@",__func__,jsonDic); NSDictionary *body = jsonDic[@"body"]; token = body[@"access_token"]; NSInteger expire_in = [body[@"expires_in"] integerValue]; response(token,expire_in); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"%s error:%@",__func__,error.debugDescription); response(token,0); }]; } //获取用户token - (void)getUserTokenWithUsername:(NSString *)username appToken:(NSString *)appToken clientId:(NSString *)clientId expires:(NSInteger)expires completion:(void (^)(NSString *userToken))response { //环信MQTT REST API地址 通过console后台[MQTT]->[服务概览]->[服务配置]下[REST API地址]获取 NSString *urlString = [NSString stringWithFormat:@"%@/openapi/rm/user/token",self.restapi]; //初始化一个AFHTTPSessionManager AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; //设置请求体数据为json类型 manager.requestSerializer = [AFJSONRequestSerializer serializer]; //设置响应体数据为json类型 manager.responseSerializer = [AFJSONResponseSerializer serializer]; //请求体,参数(NSDictionary 类型) NSDictionary *parameters = @{ @"username":username, @"expires_in":@(expires),//过期时间,单位为秒,默认为3天,如需调整,可提工单调整 @"cid":clientId }; NSLog(@"%s\n urlString:%@\n parameters:%@\n",__func__,urlString,parameters); __block NSString *token = @""; [manager POST:urlString parameters:parameters headers:@{@"Authorization":appToken} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSError *error = nil; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:responseObject options:NSJSONWritingPrettyPrinted error:&error]; NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error]; NSLog(@"%s jsonDic:%@",__func__,jsonDic); NSDictionary *body = jsonDic[@"body"]; token = body[@"access_token"]; response(token); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"%s error:%@",__func__,error.debugDescription); response(token); }]; } ==== 2.3 连接服务器 ==== 配置连接密码、cleansession标志、心跳间隔、超时时间等信息,调用connect()函数连接至环信MQTT消息云。 // 从console管理平台获取连接地址 [self.manager connectTo:self.host port:self.port tls:self.tls keepalive:45 clean:true auth:true user:userName pass:userToken will:false willTopic:nil willMsg:nil willQos:MQTTQosLevelAtMostOnce willRetainFlag:false withClientId:self.clientId securityPolicy:nil certificates:nil protocolLevel:MQTTProtocolVersion50 connectHandler:^(NSError *error) { }]; ==== 2.4 订阅(subscribe) ==== === 2.4.1 订阅主题&取消订阅主题 === 当客户端成功连接环信MQTT消息云后,通过设置subscriptions参数值实现订阅主题与取消订阅主题 。当subscriptions非空时,订阅主题;当subscriptions为空时,取消订阅主题; /** 订阅主题 格式为 xxx/xxx/xxx 可以为多级话题 @{@"xxx/xxx/xxx...":@(1)} qos定义{ 0: 最多一次,1:至少一次 2:仅一次} */ self.manager.subscriptions = @{[NSString stringWithFormat:@"%@/IOS", self.rootTopic]:@(self.qos),[NSString stringWithFormat:@"%@/IOS_TestToic", self.rootTopic]:@(1)}; /** 取消订阅主题 */ self.manager.subscriptions = @{}; === 2.4.2 接收消息 === 接收从服务器接受订阅消息。 /* * MQTTSessionManagerDelegate */ - (void)handleMessage:(NSData *)data onTopic:(NSString *)topic retained:(BOOL)retained { /* * MQTTClient: process received message */ NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; [self.receiveMsgs insertObject:[NSString stringWithFormat:@"RecvMsg from Topic: %@ Body: %@", topic, dataString] atIndex:0]; [self.tableView reloadData]; } ==== 2.5 发布消息(publish) ==== 向指定topic发送消息 - (void)send { /* * MQTTClient: send data to broker */ [self.manager sendData:[self.messageTextField.text dataUsingEncoding:NSUTF8StringEncoding] topic:[NSString stringWithFormat:@"%@/%@", self.rootTopic, @"IOS"]//此处设置多级子topic qos:self.qos retain:FALSE]; } ==== 2.6 断开连接 ==== MQTT client发送断开连接请求。 /* * 断开连接 */ - (void)disConnect { [self.manager disconnectWithDisconnectHandler:^(NSError *error) { }]; self.manager.subscriptions = @{}; } ==== 2.7 重新连接 ==== MQTT client发送重新连接请求。 /* * 重新连接 */ - (void)connect { [self.manager connectToLast:^(NSError *error) { }]; } ===== 3. 更多信息 ===== * 完整demo示例,请参见[[https://github.com/jinliang04551/MQTTChatDemo.git|demo下载]]。 * 目前MQTT客户端支持多种语言,请参见 [[http://docs-im.easemob.com/playground/message/sdkdownload|SDK下载]]。 * 如果您在使用MQTT服务中,有任何疑问和建议,欢迎您[[http://docs-im.easemob.com/playground/message/msgcontact|联系我们]]。