MQTT在RUST的使用整理(2024.6.18)

MQTT在RUST的使用整理(2024.6.18)

MQTT服务器搭建:开源的有两款,EMQX和Mosquitto,这里选择的是EMQX页面好看点,另一款Mosquitto据说比较轻型

ubuntu快速开始

一、EMQX安装

  1. 配置安装源
curl -s https://assets.emqx.com/scripts/install-emqx-deb.sh | sudo bash
  1. apt安装
sudo apt-get install emqx
  1. 启动(没有权限就加sudo)
emqx start
  1. 终端管理网站(可选,主要用于监控)

http://127.0.0.1:18083(用户名:admin,密码:public)

内网IP也是可以访问的18083网页端口的,如果要在内网之间进行通讯,请将防火墙端口开启

sudo ufw allow 1883

二、Rust使用MQTT

Rust中MQTT相关的库 paho-mqtt 、 rumqttc

以下用paho-mqtt,具体可以参照库的example进行更改。

这里做一个同时能够发送和接受的简易服务进行测试

新建一个项目

cargo new mqtt-one

首先定义几个常量,都是些通讯配置

/// 通讯IP和端口
const DFLT_BROKER:&str = "tcp://192.168.1.111:1883";  
/// 客户端名称,自定义的,用于区分服务
const DFLT_CLIENT:&str = "test_center";
/// 发布的频道,定义为数组可以加多个,可自定义的
const DFLT_PU_TOPICS:&[&str] = &["Robot_Request"];
///订阅的频道,即监听、收信息的,可自定义的
const DFLT_SU_TOPICS:&[&str] = &["Robot_Reply""Robot_Request"];
/// QOS,通讯服务质量,有0、1、2 数字越高越严格,同时也越吃性能  
const QOS:i32 = 2;	  
/// 与订阅的频道个数一致,这样可以根据不同频道使用不同通讯服务质量                               
const DFLT_QOS:&[i32] = &[0,2];                         

初始化mqtt连接方法

// 初始化mqtt连接,返回一个cli客户端
fn init_mqtt_connect()->Result<Client,Box<dyn std::error::Error>>{
    let host = DFLT_BROKER.to_string();
    // 设置客户端的配置,连接的URL,使用的ID
    let create_opts = mqtt::CreateOptionsBuilder::new().server_uri(host).client_id(DFLT_CLIENT.to_string()).finalize();
    // 创建一个连接的客户端
    let cli = mqtt::Client::new(create_opts).expect("创建连接客户端出错");
    // 设置连接时的配置参数
    let conn_opts = mqtt::ConnectOptionsBuilder::new()
        .keep_alive_interval(Duration::from_secs(20))
        .clean_session(false)
        .finalize();
    // let conn_opts = mqtt::ConnectOptionsBuilder::new().keep_alive_interval(Duration::from_secs(20)).clean_session(true).finalize();
    // 根据配置建立连接
    if let Err(e) = cli.connect(conn_opts) {
        println!("无法连接指定端口的mqtt服务器:\n\t{:?}", e);
    }
    // 客户端订阅频道
    subscribe_topics(&cli);
    Ok(cli)
}

订阅、发送、重联的API接口方法

/// 向频道发送信息
fn send_msg(cli:Client,content:String){
    
    let msg = mqtt::Message::new(DFLT_PU_TOPICS[0], content.clone(), QOS);
    let _tok = cli.publish(msg).expect("频道发布信息出错");
    println!("发送信息:{}",content);
}

/// 订阅频道
fn subscribe_topics(cli: &mqtt::Client) {
    if let Err(e) = cli.subscribe_many(DFLT_SU_TOPICS, DFLT_QOS) {
        println!("Error subscribes topics: {:?}", e);
        process::exit(1);
    }
}

/// 尝试重联
fn try_reconnect(cli: &mqtt::Client) -> bool
{
    println!("Connection lost. Waiting to retry connection");
    for _ in 0..12 {
        std::thread::sleep(Duration::from_millis(5000));
        if cli.reconnect().is_ok() {
            println!("Successfully reconnected");
            return true;
        }
    }
    println!("Unable to reconnect after several attempts.");
    false
}

汇总

main.rs文件

use std::{
    process, thread, time::Duration
};
use paho_mqtt as mqtt;
use mqtt::Client;


const DFLT_BROKER:&str = "tcp://192.168.1.111:1883";  //通讯IP和端口
const DFLT_CLIENT:&str = "test_center";                //客户端名称,自定义的,用于区分服务
const DFLT_PU_TOPICS:&[&str] = &["Robot_Request"];    //发布的频道,定义为数组可以加多个
const DFLT_SU_TOPICS:&[&str] = &["Robot_Reply","Robot_Request"];      //订阅的频道,即监听、收信息的
const QOS:i32 = 2;	                                    //QOS  通讯质量,有0、1、2 数字越高越严格,同时也越吃性能
const DFLT_QOS:&[i32] = &[0,2];                         //与订阅的频道个数一致,这样可以根据不同频道使用不同通讯质量

fn main() {
    let content="Hello,MQTT".to_string(); //要发送的内容

    let cli = init_mqtt_connect().expect("init error");
    let cli_t=cli.clone();
    // 建立一个线程,定时向主题发送信息
    thread::spawn(move||{
        println!("aha~~~~~~~~~");
        for _i in 0..10{
            send_msg(cli_t.clone(), content.clone());
            std::thread::sleep(Duration::from_millis(1000));
        }
    });
    let rx = cli.start_consuming();
    // 这里应该会一直监听,接收信息
    for msg in rx.iter() {
        if let Some(msg) = msg {
            
            let msg_string=msg.to_string();
            // let last=(msg_string.len()).min(20);
            println!("收到信息:{:?}", &msg_string);

        }
        else if !cli.is_connected() {
            if try_reconnect(&cli) {
                println!("Resubscribe topics...");
                subscribe_topics(&cli);
            } else {
                break;
            }
        }
    }
}


// 初始化mqtt连接,返回一个cli客户端
fn init_mqtt_connect()->Result<Client,Box<dyn std::error::Error>>{
    let host = DFLT_BROKER.to_string();
    // 设置客户端的配置,连接的URL,使用的ID
    let create_opts = mqtt::CreateOptionsBuilder::new().server_uri(host).client_id(DFLT_CLIENT.to_string()).finalize();
    // 创建一个连接的客户端
    let cli = mqtt::Client::new(create_opts).expect("创建连接客户端出错");
    // 设置连接时的配置参数
    let conn_opts = mqtt::ConnectOptionsBuilder::new()
        .keep_alive_interval(Duration::from_secs(20))
        .clean_session(false)
        .finalize();
    // let conn_opts = mqtt::ConnectOptionsBuilder::new().keep_alive_interval(Duration::from_secs(20)).clean_session(true).finalize();
    // 根据配置建立连接
    if let Err(e) = cli.connect(conn_opts) {
        println!("无法连接指定端口的mqtt服务器:\n\t{:?}", e);
    }
    // 客户端订阅频道
    subscribe_topics(&cli);
    Ok(cli)
}

/// 向频道发送信息
fn send_msg(cli:Client,content:String){
    
    let msg = mqtt::Message::new(DFLT_PU_TOPICS[0], content.clone(), QOS);
    let _tok = cli.publish(msg).expect("频道发布信息出错");
    println!("发送信息:{}",content);
}

/// 订阅频道
fn subscribe_topics(cli: &mqtt::Client) {
    if let Err(e) = cli.subscribe_many(DFLT_SU_TOPICS, DFLT_QOS) {
        println!("Error subscribes topics: {:?}", e);
        process::exit(1);
    }
}

/// 尝试重联
fn try_reconnect(cli: &mqtt::Client) -> bool
{
    println!("Connection lost. Waiting to retry connection");
    for _ in 0..12 {
        std::thread::sleep(Duration::from_millis(5000));
        if cli.reconnect().is_ok() {
            println!("Successfully reconnected");
            return true;
        }
    }
    println!("Unable to reconnect after several attempts.");
    false
}

Cargo.toml文件

[package]
name = "mqtt_one"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
paho-mqtt="0.12.3"
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值