在ubuntu上安装测试MQTT

348 阅读7分钟

在ubuntu上安装测试MQTT

1.引入mosquitto仓库并更新

sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
sudo apt-get update

2. 执行以下命令安装mosquitto包

sudo apt-get install mosquitto

3. 安装mosquitto开发包

sudo apt-get update
sudo apt-get install mosquitto-dev

4. 安装mosquitto客户端

sudo apt-get install mosquitto-clients

5.查询mosquitto是否正确运行

sudo service mosquitto status 

运行结果:

运行结果

status运行结果

6. 本机测试

#打开一个终端,执行以下命令订阅主题"mqtt"
mosquitto_sub -h localhost -t "mqtt" -v

#打开另外一个终端,发布消息到主题 “mqtt”
mosquitto_pub -h localhost -t "mqtt" -m "Hello MQTT"

#现在你会看到消息被显示在前一个终端上了.

【-h】指定要连接的MQTT服务器 
【-t】订阅主题,此处为mqtt 
【-v】打印更多的调试信息

7. 网络测试(test.mosquitto.org

#通过以下命令,可以定于到官放所有测试的mqtt信息,当然你发布的信息别人也能订阅到
mosquitto_sub -h test.mosquitto.org -t "#" -v

#也可以在官方mqtt服务下发布自己专属的信息
mosquitto_sub -h test.mosquitto.org -t  "myxyz123"  -v

#订阅自己的信息
mosquitto_pub -h test.mosquitto.org -t "myxyz123"  -m  "hello mqtt"

test.mosquitto.org 支持加密和不加密MQTT消息模式,也支持用TCP或者Websocket作为承载,可以通过wireshark抓包来观察不同的包格式.

8. MQTT权限配置

前面我们基于Mosquitto服务器已经搭建成功了,但是默认是允许匿名用户登录,对于正式上线的项目则是需要进行用户认证(当然,用户一般都会与数据库映射,不过在这里我们就会直接将用户写入配置文件中)

1、Mosquitto服务器的配置文件为 /etc/mosquitto/mosquitto.conf,关于用户认证的方式和读取的配置都在这个文件中进行配置文件参数说明:

IDallow_anonymouspassword_file acl_fileresult
1True(默认)  允许匿名方式登录
2FALSEpassword_file 开启用户验证机制
3FALSEpassword_fileacl_file开启用户验证机制,但访问控制不起作用
4TRUEpassword_fileacl_file用户名及密码不为空,将自动进行用户验证且受到访问控制的限制;用户名及密码为空,将不进行用户验证且受到访问控制的限制
5FALSE  无法启动服务
  • allow_anonymous 允许匿名
  • password-file 密码文件
  • acl_file 访问控制列表

2、修改配置文件

命令:sudo vi /etc/mosquitto/mosquitto.conf

sudo vim /etc/mosquitto/mosquitto.conf

修改如下:

 # Place your local configuration in /etc/mosquitto/conf.d/
 #
 # A full description of the configuration file is at
 # /usr/share/doc/mosquitto/examples/mosquitto.conf.example
 
  pid_file /var/run/mosquitto.pid
 
  persistence true
  persistence_location /var/lib/mosquitto/
 
  log_dest file /var/log/mosquitto/mosquitto.log
 
  include_dir /etc/mosquitto/conf.d

  allow_anonymous  false
  
  password_file /etc/mosquitto/pwfile
  acl_file  /etc/mosquitto/acl

3、添加用户信息

sudo mosquitto_passwd -c /etc/mosquitto/pwfile summergao

命令解释: -c 创建一个用户、/etc/mosquitto/pwfile.example 是将用户创建到 pwfile.example  文件中、summergao是用户名。 

      同样连续会提示连续输入两次密码。注意第二次创建用户时不用加 -c 如果加 -c 会把第一次创建的用户覆盖。

      至此两个用户创建成功,此时如果查看 pwfile.example 文件会发现其中多了两个用户。

4、添加Topic和用户的关系

sudo vim /etc/mosquitto/acl

修改如下:

user summergao
topic write mtopic/#

user summergao
topic read mtopic/#

5、用户认证测试

(1)重启Mosquitto步骤    

  查看mosquitto的进程

  命令:ps -aux|grep mosquitto

(2)杀死进程

  命令:sudo kill -9 pid

(3)启动

  命令: mosquitto -c /etc/mosquitto/mosquitto.conf

sudo mosquitto -c /etc/mosquitto/mosquitto.conf

(4)订阅端启动(不加用户)

mosquitto_sub -h localhost -t "mtopic" -v

订阅端启动(加用户)

mosquitto_sub -h localhost -t "mtopic" -v -u summergao -P summergao

(5)发布端启动

mosquitto_pub -h localhost -t "mtopic" -u summergao -P summergao -m "Hello MQTT"

完整截图:

六、MQTT实现(Java语言)

注意:由于我们在上面配置了MQTT的用户权限控制,所以下面的用户只能使用summergao登录,否则项目会运行报错,而且我们在上面设置的访问控制列表中只有mtopic主题,所以我们必须使用此主题,否则,订阅者会收不到已发布的主题内容(已经测试过了)

下面是我们Java语言实现的MQTT服务的发布/订阅

1、添加Maven依赖

    <dependency>
      <groupId>org.eclipse.paho</groupId>
      <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
      <version>1.1.1</version>
    </dependency>

2、ServerMQTT.class

package com.stonegeek;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
/**
 * Created by StoneGeek on 2018/6/5.
 * 博客地址:http://www.cnblogs.com/sxkgeek
 * 服务器向多个客户端推送主题,即不同客户端可向服务端订阅相同的主题
 */
public class ServerMQTT {
    //tcp://MQTT安装的服务器地址:MQTT定义的端口号
    public static final String HOST = "tcp://127.0.0.1:1883";
    //定义一个主题
    public static final String TOPIC = "mtopic";
    //定义MQTT的ID,可以在MQTT服务配置中指定
    private static final String clientid = "server11";

    private MqttClient client;
    private MqttTopic topic11;
    private String userName = "summergao";
    private String passWord = "summergao";

    private MqttMessage message;

    /**
     * 构造函数
     * @throws MqttException
     */
    public ServerMQTT() throws MqttException {
        // MemoryPersistence设置clientid的保存形式,默认为以内存保存
        client = new MqttClient(HOST, clientid, new MemoryPersistence());
        connect();
    }

    /**
     *  用来连接服务器
     */
    private void connect() {
        MqttConnectOptions options = new MqttConnectOptions();
        options.setCleanSession(false);
        options.setUserName(userName);
        options.setPassword(passWord.toCharArray());
        // 设置超时时间
        options.setConnectionTimeout(10);
        // 设置会话心跳时间
        options.setKeepAliveInterval(20);
        try {
            client.setCallback(new PushCallback());
            client.connect(options);

            topic11 = client.getTopic(TOPIC);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     *
     * @param topic
     * @param message
     * @throws MqttPersistenceException
     * @throws MqttException
     */
    public void publish(MqttTopic topic , MqttMessage message) throws MqttPersistenceException,
            MqttException {
        MqttDeliveryToken token = topic.publish(message);
        token.waitForCompletion();
        System.out.println("message is published completely! "
                + token.isComplete());
    }

    /**
     *  启动入口
     * @param args
     * @throws MqttException
     */
    public static void main(String[] args) throws MqttException {
        ServerMQTT server = new ServerMQTT();

        server.message = new MqttMessage();
        server.message.setQos(1);
        server.message.setRetained(true);
        server.message.setPayload("hello,topic11".getBytes());
        server.publish(server.topic11 , server.message);
        System.out.println(server.message.isRetained() + "------ratained状态");
    }
}

3、ClientMQTT .class

package com.stonegeek;
import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
/**
 * Created by StoneGeek on 2018/6/5.
 * 博客地址:http://www.cnblogs.com/sxkgeek
 */
public class ClientMQTT {
    public static final String HOST = "tcp://127.0.0.1:1883";
    public static final String TOPIC = "mtopic";
    private static final String clientid = "client11";
    private MqttClient client;
    private MqttConnectOptions options;
    private String userName = "summergao";
    private String passWord = "summergao";

    private ScheduledExecutorService scheduler;

    private void start() {
        try {
            // host为主机名,clientid即连接MQTT的客户端ID,一般以唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
            client = new MqttClient(HOST, clientid, new MemoryPersistence());
            // MQTT的连接设置
            options = new MqttConnectOptions();
            // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,这里设置为true表示每次连接到服务器都以新的身份连接
            options.setCleanSession(true);
            // 设置连接的用户名
            options.setUserName(userName);
            // 设置连接的密码
            options.setPassword(passWord.toCharArray());
            // 设置超时时间 单位为秒
            options.setConnectionTimeout(10);
            // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
            options.setKeepAliveInterval(20);
            // 设置回调
            client.setCallback(new PushCallback());
            MqttTopic topic = client.getTopic(TOPIC);
            //setWill方法,如果项目中需要知道客户端是否掉线可以调用该方法。设置最终端口的通知消息
            options.setWill(topic, "close".getBytes(), 2, true);

            client.connect(options);
            //订阅消息
            int[] Qos  = {1};
            String[] topic1 = {TOPIC};
            client.subscribe(topic1, Qos);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws MqttException {
        ClientMQTT client = new ClientMQTT();
        client.start();
    }
}

4、PushCallback.class

package com.stonegeek;

import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttMessage;

/**
 * Created by StoneGeek on 2018/6/5.
 * 博客地址:http://www.cnblogs.com/sxkgeek
 * 发布消息的回调类 
 *
 * 必须实现MqttCallback的接口并实现对应的相关接口方法CallBack 类将实现 MqttCallBack。 
 * 每个客户机标识都需要一个回调实例。在此示例中,构造函数传递客户机标识以另存为实例数据。 
 * 在回调中,将它用来标识已经启动了该回调的哪个实例。 
 * 必须在回调类中实现三个方法: 
 *
 *  public void messageArrived(MqttTopic topic, MqttMessage message)接收已经预订的发布。 
 *
 *  public void connectionLost(Throwable cause)在断开连接时调用。 
 *
 *  public void deliveryComplete(MqttDeliveryToken token)) 
 *  接收到已经发布的 QoS 1 或 QoS 2 消息的传递令牌时调用。 
 *  由 MqttClient.connect 激活此回调。 
 */
public class PushCallback implements MqttCallback{
    public void connectionLost(Throwable cause) {
        // 连接丢失后,一般在这里面进行重连
        System.out.println("连接断开,可以做重连");
    }

    public void deliveryComplete(IMqttDeliveryToken token) {
        System.out.println("deliveryComplete---------" + token.isComplete());
    }

    public void messageArrived(String topic, MqttMessage message) throws Exception {
        // subscribe后得到的消息会执行到这里面
        System.out.println("接收消息主题 : " + topic);
        System.out.println("接收消息Qos : " + message.getQos());
        System.out.println("接收消息内容 : " + new String(message.getPayload()));
    }
}

5、结果展示

  

  

  以上我们MQTT的简单搭建与应用就结束了,之后我们会深入了解MQTT协议的!!!

参考

www.jianshu.com/p/37f7ee7ea…

www.cnblogs.com/sxkgeek/p/9…