1.MQTT 个人理解 是一个消息转发技术,由客户发布订阅号,根据订阅号进行消息的传递。
2.在使用过程中,发送和接收消息的都是客户端,如果需要可以把一个指定的客户端当作 小服务器来用(我开发项目就这样干的,只有我能发消息,其他客户端只能接收)。
3.废话不多说,直接撸代码。菜鸟级写的东西,写错了大神勿喷。
首先,先到官网下载个服务器端。http://mirrors.cnnic.cn/apache/activemq/activemq-apollo/1.7.1/apache-apollo-1.7.1-windows-distro.zip 我下载的是window版的
然后解压解压后跑到这个目录来 在这个目录打开dos窗口
看红框里面的
你会发现在这个目录下面多出了个yxy 文件夹 这个yxy是我随便输入的
然后 进入到yxy/etc目录打开apollo.xml文件你会看到
这段 这就是 mqtt服务器发布的请求路径 让后打开同级目录下面的user.properties文件 最后一行 你会看到 admin=password 这个就是 服务器的帐号密码
最后跑到yxy/bin 下面 打开dos界面 运行 apollo-broker.cmd run 这个命令 那么服务器你就启动好了
在浏览器输入http://127.0.0.1:61680 就可以看到服务器登录界面了 输入admin=password 登录进去 自己慢慢看
现在来讲客户端 我使用的是java 所以只说java版本的
首先下载mqtt java的驱动包
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.0.2</version>
</dependency>
直接代码撸上
这个是接收端的代码
package com.xdb.mqtt.client;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
public class MyMqttClient {
private MqttBean bean;
private MqttClient client;
private MqttConnectOptions options;
/**
* 初始化配置
*/
private void init() {
if(bean==null){
bean = getConfig();
}
}
/**
* 我这里是手动指定客户端连接的初始化数据
*
* @return
*/
private MqttBean getConfig() {
MqttBean bean=new MqttBean();
//这里使用的是tcp协议 所以我用这个端口 其他协议可以查询etc/apollo.xml文件里面的配置
bean.setMqttServerHost("tcp://127.0.0.1:61613");
bean.setClientid("yixiangyue");
bean.setUserName("admin");
bean.setPassWord("password");
//这里是我这个客户端订阅那些信息
bean.setTopic(new String[]{"abcde","rrrr"});
return bean;
}
public void start() throws Exception {
/*网络获取配置信息*/
init();
/*初始化配置*/
client = new MqttClient(bean.getMqttServerHost(),bean.getClientid(), new MemoryPersistence());
options = new MqttConnectOptions();
/* 在客户端重启时 true:重新与服务器建立连接,默认是true false:不重新建立连接 */
options.setCleanSession(MqttConnectOptions.CLEAN_SESSION_DEFAULT);
/* 设置登录服务器的帐号密码 */
options.setUserName(bean.getUserName());
options.setPassword(bean.getPassWord().toCharArray());
/*设置超时时间*/
options.setConnectionTimeout(100);
options.setKeepAliveInterval(200);
client.setCallback(new PushCallBack());
/*自己发布一个独立的订阅*/
MqttTopic topic=client.getTopic(bean.getClientid());
//这里个人理解 是指在当前客户端被关闭时 会接受到这个消息,第二个参数指消息的权重顺序,第三个是只此消息是否在服务器保留(文档上百度翻译是这么描述)
options.setWill(topic,new String(bean.getClientid()+"已经关闭").getBytes(), 2, true);
// 多个订阅表示 接收的顺序 自己测试的结果是这样 暂时还没发现其他
client.connect(options);
int[] qos = new int[bean.getTopic().length];
for(int i=0;i<bean.getTopic().length;i++){
qos[i]=i+1;
}
client.subscribe(bean.getTopic(), qos);
}
}
发送端
package com.mqtt.util;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
public class MqttServer {
private static final String serverURI = "tcp://192.168.1.6:61613";
private static final String clientId = "server";
private MqttClient client;
private String userName = "admin";
private String passWord = "password";
private MqttMessage message;
public MqttServer(){
try{
client = new MqttClient(serverURI, clientId, new MemoryPersistence());
connect();
}catch (Exception e) {
e.printStackTrace();
}
}
private void connect()throws Exception {
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(false);
options.setUserName(userName);
options.setPassword(passWord.toCharArray());
options.setConnectionTimeout(100);
options.setKeepAliveInterval(200);
client.setCallback(new PushCallBack());
client.connect(options);
}
/**
* 消息群发
* 所以
* @param tipic
* @throws Exception
*/
public void publishMessage(MqttTopic topic,MqttMessage message)throws Exception{
topic.publish(message);
}
public void publishMessage(Set<String> list,MqttMessage message)throws Exception{
for(String topic:list){
this.client.getTopic(topic).publish(message);
}
}
public static void main(String[] args)throws Exception {
MqttServer server = new MqttServer();
SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
server.message = new MqttMessage();
server.message.setQos(2);
server.message.setRetained(true);
String message="服务器推送来的消息["+df.format(new Date())+"]";
server.message.setPayload(message.getBytes());
//这里的abcde是指要把这个消息发给这个订阅 所有订阅了这个客户端都会接收到信息
server.publishMessage(server.getClient().getTopic("abcde"), server.message);
}
}
这里是回调
import java.text.SimpleDateFormat;
import java.util.Date;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
public class PushCallBack implements MqttCallback {
/**
* 当前客户端已经被断开
*/
public void connectionLost(Throwable throwable) {
System.out.println("连接断开,可以做重连");
}
/**
* 发送消息 确认对方已经收到
*/
public void deliveryComplete(IMqttDeliveryToken arg0) {
System.out.println("deliveryComplete---------" + arg0.isComplete());
}
/**
* 接收到服务端发来的消息
*/
public void messageArrived(String title, MqttMessage message) throws Exception {
// subscribe后得到的消息会执行到这里面
System.out.println("接收消息主题 : " + title);
System.out.println("接收消息Qos : " + message.getQos());
System.out.println("接收消息内容 : " + new String(message.getPayload()));
SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("接收时间:"+df.format(new Date()));
System.out.println("\n\n\n");
}
}
写到这应该差不多了
刚刚学习的同学 也先不看代码 拷贝下来先运行成功了 再慢慢看
这里感谢以前写过类似文章的各位大神 我也是到处看看 自己慢慢试 试出来的 自己也去看了下 API 发现这个
这里是回调
new MqttClient(serverURI, clientId, new MemoryPersistence()); 为客户端设置一个clientID 似乎没什么用 没办法在服务器直接找到这个ID 指定推送消息 所以想要指定一个一个消息推送到客户端 我个人的做法是为每个客户端 指定一个 唯一的 订阅
好了 就写到这样
上班撸代码
这里是回调