一、MQTT介绍

链接1(菜鸟教程):https://www.runoob.com/w3cnote/mqtt-intro.html

连接2(MQTT中文网):http://mqtt.p2hp.com/

连接3(Android开发之Mqtt的使用):https://blog.csdn.net/asjqkkkk/article/details/80714234

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)。一种基于发布/订阅(publish/subscribe)模式的“轻量级”通讯协议。构建于TCP/IP协议上,由IBM在1999年发布。

二、程序示例

 public class MqttManager {

     private static boolean initFirst = true;//是否第一次初始化mqtt标识符
private static String host = "tcp://47.106.172.221:8081";
private static String userName; //mqtt用户名
private static String passWord; //mqtt登陆密码
private static MqttManager manager;
private static MqttClient mqttClient;
private static MqttConnectOptions options;
private static String topic;//订阅的主题
private static String clientId; //客户端id private static Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1) {
KLog.d(msg.obj);
EventBus.getDefault()
.post(new MessageEventBean(AppConstants.MQTT_EVENT_TYPE, (String) msg.obj));
} else if (msg.what == 2) {
KLog.d("连接成功");
try {
KLog.d("订阅的主题:" + topic);
mqttClient.subscribe(topic, 0); } catch (Exception e) {
e.printStackTrace();
}
} else if (msg.what == 3) {
KLog.d("连接失败,系统正在重连");
}
}
}; private MqttManager() { }
private static MqttCallback myMqttCallback = new MqttCallback(){ @Override
public void messageArrived(String topic, MqttMessage message){
//subscribe后得到的消息会执行到这里面
KLog.d("messageArrived topic:"+topic);
Message msg = new Message();
msg.what = 1;
msg.obj = message.toString();
handler.sendMessage(msg);
}
@Override
public void connectionLost(Throwable cause) {
KLog.d("connectionLost cause = "+cause);
//连接丢失后,一般在这里面进行重连
try{
KLog.d("mqtt重连");
manager.startReconnect();
}catch (Exception e){
KLog.d("Exception = "+ e);
e.printStackTrace();
}
} @Override
public void deliveryComplete(IMqttDeliveryToken token) {
//publish后会执行到这里
KLog.d("deliveryComplete");
}
};
private ScheduledExecutorService scheduler; public static MqttManager getInstance() {
if (manager == null) {
manager = new MqttManager();
}
return manager;
} public void initConnection() {
if (initFirst){
KLog.d("第一次调用initConnection");
try {
clientId = Preferences.getUserAccount() + System.currentTimeMillis();//客户端标识符(本机mac地址+当前时间ms)
userName = Preferences.getUserAccount();//用户名
passWord = Preferences.getUserToken();//密码
topic = userName;
//host为主机名;clientid即连接MQTT的客户端ID,是客户端的唯一标识符;MemoryPersistence设置clientid的保存形式,默认为以内存保存
mqttClient = new MqttClient(host, clientId, new MemoryPersistence());
//MQTT的连接设置
options = new MqttConnectOptions();
//设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,这里设置为true表示每次连接到服务器都以新的身份连接
options.setCleanSession(true);
//断开后,是否自动连接
options.setAutomaticReconnect(true);
//设置连接的用户名
options.setUserName(userName);
//设置连接的密码
options.setPassword(passWord.toCharArray());
// 设置超时时间 单位为秒
options.setConnectionTimeout(10);
// 设置会话心跳时间 单位为秒 服务器会每隔1.5*(20)秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
options.setKeepAliveInterval(20);
//setWill方法,如果项目中需要知道客户端是否掉线可以调用该方法。设置最终端口的通知消息
// options.setWill(topic,"close".getBytes(),2,true);
//设置回调
mqttClient.setCallback(myMqttCallback);
KLog.d("clientId: "+clientId +", userName: "+userName+", passWord: "+passWord+", topic: "+topic);
//设置标识符状态
initFirst = false;
//mqtt第一次连接
manager.startReconnect();
} catch (Exception e) {
KLog.d("initConnection Exception: " + e);
e.printStackTrace();
}
}else {
KLog.d("网络重连后调用initConnection");
manager.startReconnect();
}
} public void startReconnect() { if (NetworkUtils.isConnected()){ if (!mqttClient.isConnected()) {
//重新连接
connect();
KLog.d("mqtt连接结束");
}else {
KLog.d("mqttClient.isConnected");
}
// scheduler = Executors.newSingleThreadScheduledExecutor();
// scheduler.scheduleAtFixedRate(new Runnable() {
// @Override
// public void run() {
//
// if (!mqttClient.isConnected()) {
// connect();
// KLog.d("mqtt连接结束");
// }
// }
// }, 0 * 1000, 10 * 1000, TimeUnit.MILLISECONDS);
}else {
KLog.d("网络不可用");
// scheduler.shutdown();
} } public void sendMsg(String msg) {
KLog.d("sendMsg");
if (mqttClient != null && mqttClient.isConnected()) {
try {
KLog.d("发送的主题:" + Preferences.getUserAccount());
String topic = Preferences.getUserAccount();
KLog.d(topic);
byte[] msgBytes = msg.getBytes();
KLog.d("0000");
mqttClient.publish(topic, msgBytes, 0, false);
KLog.d("11111111111111111");
} catch (MqttException e) {
KLog.d(e);
}
}
} //发布的主题设为pubTopic = "owh" + Preferences.getUserAccount();
//发布主题(发布主题和订阅主题应设为不同值)
public void publish(String topicName, String payload) {
if (mqttClient != null && mqttClient.isConnected()) {
// 创建和配置一个消息
MqttMessage message = new MqttMessage(payload.getBytes());
message.setPayload(payload.getBytes());
message.setQos(0);
try {
KLog.d("1111");
mqttClient.publish(topicName, message);
KLog.d("2222");
} catch (MqttException e) {
KLog.d("publish : " + e.toString());
}
}
} private void connect() { ThreadPoolManager.getInstance().execute(new Runnable() {
@Override
public void run() {
try {
mqttClient.connect(options);
Message msg = Message.obtain();
msg.what = 2;
handler.sendMessage(msg);
} catch (Exception e) {
e.printStackTrace();
Message msg = Message.obtain();
msg.what = 3;
handler.sendMessage(msg);
}
}
}); // new Thread(new Runnable() {
//
// @Override
// public void run() {
// try {
// mqttClient.connect(options);
// Message msg = new Message();
// msg.what = 2;
// handler.sendMessage(msg);
// } catch (Exception e) {
// e.printStackTrace();
// Message msg = new Message();
// msg.what = 3;
// handler.sendMessage(msg);
// }
// }
// }).start();
} //断开连接
public static void mqttDisconnect(){
if(mqttClient !=null && mqttClient.isConnected()){
try{
mqttClient.disconnect();
}catch (MqttException e){
KLog.d("mqtt disconnect error");
e.printStackTrace();
}
}
} }

三、注意事项

1、MQTT的客户端id(clientId)须唯一。在此项目中clientId = 本机mac地址 + 当前时间(ms)。

2、一个客户端的一个MQTT连接最好只new一个对象,避免一台设备产生多个客户端账号。

当多个发布(/订阅)的clientId相同时,会发生Mqtt反复重连的现象,无法正常发送或接收消息。

当多个发布(/订阅)的clientId不同时,会造成一台设备多个Mqtt账号同时在线,占用了多余的服务器资源。

3、一个客户端的发布Topic和订阅Topic不应相同。

Android MQTT的发布与订阅的更多相关文章

  1. MQTT介绍(3)java模拟MQTT的发布,订阅

    MQTT目录: MQTT简单介绍 window安装MQTT服务器和client java模拟MQTT的发布,订阅 在此强调一下mqtt的使用场景: 1.不可靠.网络带宽小的网络 2.运行的设备CPU. ...

  2. 转MQTT--Python进行发布、订阅测试

    前言  使用python编写程序进行测试MQTT的发布和订阅功能.首先要安装:pip install paho-mqtt 测试发布(pub)  我的MQTT部署在阿里云的服务器上面,所以我在本机上编写 ...

  3. MQTT 消息 发布 订阅

    当连接向一个mqtt服务器时,clientId必须是唯一的.设置一样,导致client.setCallback总是走到 connectionLost回调.报connection reset.调查一天才 ...

  4. (转)SqlServer 数据库同步的两种方式 (发布、订阅),主从数据库之间的同步

    最近在琢磨主从数据库之间的同步,公司正好也需要,在园子里找了一下,看到这篇博文比较详细,比较简单,本人亲自按步骤来过,现在分享给大家. 在这里要提醒大家的是(为了更好的理解,以下是本人自己理解,如有错 ...

  5. (原)3.2 Zookeeper应用 - 数据的发布与订阅

    本文为原创文章,转载请注明出处,谢谢 数据的发布与订阅 1.应用 服务端监听数据改变,客户端创建/更新节点数据,客户端提供数据,服务端处理 2.原理 客户端监控节点数据改变事件(例如配置信息,下图的c ...

  6. MSSQL复制中的发布与订阅

    准备条件 1.2台服务器 2.WINDOWS SERVER 2008 64bit + 3.SQL SERVER 2008 R2 + 4.MSSQLSERVER服务与MSSQLAGENT服务正常运行中 ...

  7. 知方可补不足~SQL2008中的发布与订阅模式

    回到目录 作用:完成数据库与数据库的数据同步 原理:源数据库发布需要同时的表,存储过程,或者函数:目标数据库去订阅它,当源发生变化时,目标数据库自己同步,注意,由于这个过程是SQL自动完成的,所以要求 ...

  8. RabbitMQ官方中文入门教程(PHP版) 第三部分:发布/订阅(Publish/Subscribe)

    发布/订阅 在上篇教程中,我们搭建了一个工作队列.每个任务之分发给一个工作者(worker).在本篇教程中,我们要做的之前完全不一样——分发一个消息给多个消费者(consumers).这种模式被称为“ ...

  9. 【SQL Sever】实现SQL Sever的发布。订阅。 双机热备

    实现SQL Sever的发布和订阅  最大的好处就是: 可以实现读写分离,增删改操作在主数据库服务器上进行,查询在备份数据库服务器上进行.一方面提高软件执行效率,另一方面也减轻主库压力. 本次实现发布 ...

随机推荐

  1. ELK-6.5.3学习笔记–elk基础环境安装

    本文预计阅读时间 13 分钟 文章目录[隐藏] 1,准备工作. 2,安装elasticsearch. 3,安装logstash. 4,安装kibana 以往都是纸上谈兵,毕竟事情也都由部门其他小伙伴承 ...

  2. JavaScript应懂的概念

    目录 垃圾回收 函数作用域, 块级作用域和词法作用域 调用堆栈 原始类型 值类型和引用类型 隐式, 显式, 名义和鸭子类型 == 与 ===, typeof 与 instanceof this, ca ...

  3. synchronized锁住的是代码还是对象,以及synchronized底层实现原理

    synchronized (this)原理:涉及两条指令:monitorenter,monitorexit:再说同步方法,从同步方法反编译的结果来看,方法的同步并没有通过指令monitorenter和 ...

  4. servlet和Struts2的线程安全性对比

    1.>在servlet中,定义成员变量是不安全的,,因为,每次请求操作的是该同一个成员变量,,会出现线程不安全的问题. 2.>而在struts2中,在Action中定义成员变量是安全的,, ...

  5. js数组与对象的区别

    数组和对象两者都可以用来表示数据的集合,曾一度搞不清楚”数组”(array)和”对象”(object)的根本区别在哪里. 有一个数组a=[1,2,3,4],还有一个对象a={0:1,1:2,2:3,3 ...

  6. tab栏切换效果案例

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. php函数nl2br的反函数br2nl 将html中的br换行符转换为文本输入中的换行符

    下面这几个方法将能够帮你解决这个问题. PHP版将html中的<br />换行符转换为文本框中的换行符: 代码如下: function br2nl($text){ return preg_ ...

  8. 清北学堂提高组突破营游记day4

    今天主攻图论. 对于这道题,30分做法是暴力搜索全部来判断是否有异样. 对于满分做法,利用带权并查集.? 又带我们串了一边LCA 安利个人LCA博客. spfa代码.原理:循环队列. 然后是floyd ...

  9. python接口自动化六(参数化也就是把之前敲过的代码封装成方法)

    前言 前面一篇实现了参数的关联,那种只是记流水账的完成功能,不便于维护,也没什么可读性,接下来这篇可以把每一个动作写成一个函数,这样更方便了. 参数化的思维只需记住一点:不要写死 (由于博客园登录机制 ...

  10. redis主从+keepalived实现高可用技术

    Redis是我们当下比较流行使用的非关系数据库,可支持多样化的数据类型,多线程高并发支持,redis运行在内存拥有更快的读写.因为redis的表现如此出色,如何能保障redis在运行中能够应对宕机故障 ...