MQTT 实战

前言

mqtt现在在物联网上面使用的还是比较多的,其实整体上mqtt也满足分布式的思想,可以实现一对多,多对一。再加上简答的三种Qos策略,也算是一种比较好的方式。但是需要broker这种思想设计,其实也使系统的不稳定性和复杂性多了一些弊端。这种方式也是ros1 的弊端。所以在最新的ros2和zeromq上面,也尽量的去掉了broker这种思想。mqtt因为其简单,便捷,独到的设计,还是被选择大量用在了系统并不复杂的嵌入式设备上。

综述

简介

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
在这里插入图片描述

特点

MQTT协议工作在低带宽、不可靠的网络的远程传感器和控制设备通讯而设计的协议,它具有以下主要的几项特性:

  1. 使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合。 对负载内容屏蔽的消息传输。

  2. 使用TCP/IP提供网络连接。主流的MQTT是基于TCP连接进行数据推送的,但是同样有基于UDP的版本,叫做MQTT-SN。这两种版本由于基于不同的连接方式,优缺点自然也就各有不同了。

  3. 有三种消息发布服务质量:
    “至多一次”,消息发布完全依赖底层TCP/IP网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。这一种方式主要普通APP的推送,倘若你的智能设备在消息推送时未联网,推送过去没收到,再次联网也就收不到了。
    “至少一次”,确保消息到达,但消息重复可能会发生。
    “只有一次”,确保消息到达一次。在一些要求比较严格的计费系统中,可以使用此级别。在计费系统中,消息重复或丢失会导致不正确的结果。这种最高质量的消息发布服务还可以用于即时通讯类的APP的推送,确保用户收到且只会收到一次。

  4. 使用Last Will和Testament特性通知有关各方客户端异常中断的机制。 Last
    Will:即遗言机制,用于通知同一主题下的其他设备发送遗言的设备已经断开了连接。 Testament:遗嘱机制,功能类似于Last
    Will

使用方式

  1. 启动broker,即服务器代理
  2. 创建 mqtt MQTTClient_create( &client, address, client_id, MQTTCLIENT_PERSISTENCE_NONE, NULL)) < 0 )
  3. 发起连接 MQTTClient_connect( client, &conn_opts))!=MQTTCLIENT_SUCCESS )
  4. 开始订阅或发布 MQTTClient_subscribe(client, payload, 1); & MQTTClient_publishMessage(client,topic,&publish_msg,&token);
  5. 使用多种方法接收数据或者判断数据是否发送出去 MQTTClient_receive( client, &topic, &topic_len, &receive_msg, 100000)) != MQTTCLIENT_SUCCESS) &MQTTClient_waitForCompletion(client,token,time_out)
  6. 退订、断开、或者退出 MQTTClient_disconnect(client, 10000); MQTTClient_disconnect(client, 10000);

特殊功能

(1)安全功能 SSL
(2)同步功能和异步功能,我们实际项目中使用的异步的功能
(3)断开网络后重新连接,这个也是在异步中操作的,具体操作实例可参考如下文档
https://www.cnblogs.com/seacode/p/13665054.html

实例

先简单介绍以下paho mq下面的几个库,这几个库的特点主要是分为 同步,异步,是否加密
paho-mqtt3a : 一般实际开发中就是使用这个,a表示的是异步消息推送(asynchronous)。
paho-mqtt3as : as表示的是 异步+加密(asynchronous+OpenSSL)。
paho-mqtt3c : c 表示的应该是同步(Synchronize),一般性能较差,是发送+等待模式。
paho-mqtt3cs : 同上,增加了一个OpenSSL而已。

paho mqtt 库下载&安装

git clone https://github.com/eclipse/paho.mqtt.c.gi
make
make install

mqtt 的架构分为客户端和服务端,服务端的作用是broker,我在实例中使用的broker是
在这个位置下载的 https://www.emqx.com/zh/downloads?product=broker
安装上,直接执行就可以
也可以在浏览器上面查看,监控相关信息
http://127.0.0.1:18083 用户名为 admin 密码 public

两段client端的代码,在example的程序中就能够找到:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
#include<unistd.h>
#include"MQTTClient.h"

int main(int argc,char **argv)
{
    char *address="tcp://localhost:1883";
    char *client_id="publish_client";
    char *topic="mqtt_examples";
    char buf[1024];
    const int time_out=10000;
    int  rv;
    int  QOS=1;
    MQTTClient   client;
    MQTTClient_connectOptions conn_opts=MQTTClient_connectOptions_initializer;
    MQTTClient_message publish_msg=MQTTClient_message_initializer;
    MQTTClient_deliveryToken token;

    conn_opts.keepAliveInterval=60;
    conn_opts.cleansession=1;

    MQTTClient_create(&client,address,client_id,MQTTCLIENT_PERSISTENCE_NONE,NULL);
    if((rv=MQTTClient_connect(client,&conn_opts))!=MQTTCLIENT_SUCCESS)
    {
    printf("MQTTClient_connect failure:%s\n",strerror(errno));
        return 0;
    }
    publish_msg.qos=QOS;
    publish_msg.retained=0;
    while(1)
    {
        printf("enter the message you want to send\n");
        fgets(buf,sizeof(buf),stdin);
        publish_msg.payload=(void *)buf;
        publish_msg.payloadlen=strlen(buf);
        MQTTClient_publishMessage(client,topic,&publish_msg,&token);
        printf("waiting for %d seconds for publication of %s on topic %s for client with CLIENTID :%s\n",time_out/1000,buf,topic,client_id);
        rv=MQTTClient_waitForCompletion(client,token,time_out);
        printf("Message with delivery token %d delivered\n",rv);
        printf("%s\n",buf);//用于测试
        sleep(3);
    }
}

编译:gcc mqtt_publish.c -o mqtt_publish -lpaho-mqtt3c -L ./MQTT/paho.mqtt.c/ -I ./MQTT/paho.mqtt.c/src/

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include"MQTTClient.h"

int main()
{
    char *address="tcp://localhost:1883";
    char *client_id="client_sub";
    char *payload="mqtt_examples";
    int    rv,i;
    char *ptr=NULL;
    char *topic=NULL;
    int topic_len;
    MQTTClient client;
    MQTTClient_connectOptions conn_opts=MQTTClient_connectOptions_initializer;
    MQTTClient_deliveryToken token;
    MQTTClient_message *receive_msg=NULL;
    conn_opts.keepAliveInterval=60;
    conn_opts.cleansession=1;

    if((rv=MQTTClient_create(&client,address,client_id,MQTTCLIENT_PERSISTENCE_NONE,NULL))<0)
    {
        printf("MQTTClient_create failure:%s\n",strerror(errno));
        return 0;
    }
    printf("MQTTClient_create successfully\n");
    if((rv=MQTTClient_connect(client,&conn_opts))!=MQTTCLIENT_SUCCESS)
    {
        printf("MQTTClient_connect failure:%s\n",strerror(errno));
        return 0;
    }
    printf("MQTTClient_connect successfuly\n");
    MQTTClient_subscribe(client,payload,1);
    /* if((rv=MQTTClient_receive(client,&topic,&topic_len,&receive_msg,5000))!=MQTTCLIENT_SUCCESS)
    { 
        printf("MQTTClient_receive failure:%s\n",strerror(errno));
        return 0;
    }  
    printf("MQTTClient_receive successfully\n");*/
    //receive 函数放在外面传递信息不会改变
    while(1)
    {
        if((rv=MQTTClient_receive(client,&topic,&topic_len,&receive_msg,100000))!=MQTTCLIENT_SUCCESS)//最后一个参数是超时时间,单位是毫秒
        {
            printf("MQTTClient_receive failure:%s\n",strerror(errno));
            break;
        }
        printf("MQTTClient_receive successfully\n");
        ptr=receive_msg->payload;
        printf("Topic:%s\nTopic_len:%d\nmsg:",topic,topic_len);
        for(i=0;i<receive_msg->payloadlen;i++)
        {
            putchar(*ptr++);
        }
        printf("\nmsg_len:%d\nmsg_id:%d\n",receive_msg->payloadlen,receive_msg->msgid);
        sleep(3);
    }
    printf("end\n");
    MQTTClient_disconnect(client, 10000);
    MQTTClient_destroy(&client);
    return 0;
}

编译 gcc mqtt_subscribe.c -o mqtt_subscribe -lpaho-mqtt3c -L ./MQTT/paho.mqtt.c/build/output/

运行测试程序即可

参考文章:
https://blog.csdn.net/qq_43260665/article/details/88370100 测试实例
https://blog.csdn.net/weixin_42788872/article/details/106426802 实例中搭建mqtt服务器和broker
https://www.runoob.com/w3cnote/mqtt-intro.html mqtt入门概念

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值