1. 简述

一款实现了消息推送协议 MQTT v3.1 的开源消息代理软件,提供轻量级的,支持可发布/可订阅的的消息推送模式,使设备对设备之间的短消息通信变得简单,比如现在应用广泛的低功耗传感器,手机、嵌入式计算机、微型控制器等移动设备。一个典型的应用案例就是 Andy Stanford-ClarkMosquitto(MQTT协议创始人之一)在家中实现的远程监控和自动化,并在 OggCamp 的演讲上,对MQTT协议进行详细阐述。

官网:

http://www.mosquitto.org/

http://www.mosquitto.org/man/

http://www.mosquitto.org/api/

https://mosquitto.org/man/mosquitto-8.html IBM的一个server(broker)示例用法说明

2. 函数

mosquitto结构体:

struct mosquitto;
struct mosquitto_message{
int mid;
char *topic;
void *payload;
int payloadlen;
int qos;
bool retain;
};

mosquitto支持推送和订阅消息模式:

/*
* Function: mosquitto_publish
*
* Publish a message on a given topic.
*
* Parameters:
* mosq - a valid mosquitto instance.
* mid - pointer to an int. If not NULL, the function will set this
* to the message id of this particular message. This can be then
* used with the publish callback to determine when the message
* has been sent.
* Note that although the MQTT protocol doesn't use message ids
* for messages with QoS=0, libmosquitto assigns them message ids
* so they can be tracked with this parameter.
* topic - null terminated string of the topic to publish to.
* payloadlen - the size of the payload (bytes). Valid values are between 0 and
* 268,435,455.
* payload - pointer to the data to send. If payloadlen > 0 this must be a
* valid memory location.
* qos - integer value 0, 1 or 2 indicating the Quality of Service to be
* used for the message.
* retain - set to true to make the message retained.
*
* Returns:
* MOSQ_ERR_SUCCESS - on success.
* MOSQ_ERR_INVAL - if the input parameters were invalid.
* MOSQ_ERR_NOMEM - if an out of memory condition occurred.
* MOSQ_ERR_NO_CONN - if the client isn't connected to a broker.
* MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the
* broker.
* MOSQ_ERR_PAYLOAD_SIZE - if payloadlen is too large.
*
* See Also:
* <mosquitto_max_inflight_messages_set>
*/
libmosq_EXPORT int mosquitto_publish(struct mosquitto *mosq, int *mid, const char *topic, int payloadlen, const void *payload, int qos, bool retain);
/*
* Function: mosquitto_subscribe
*
* Subscribe to a topic.
*
* Parameters:
* mosq - a valid mosquitto instance.
* mid - a pointer to an int. If not NULL, the function will set this to
* the message id of this particular message. This can be then used
* with the subscribe callback to determine when the message has been
* sent.
* sub - the subscription pattern.
* qos - the requested Quality of Service for this subscription.
*
* Returns:
* MOSQ_ERR_SUCCESS - on success.
* MOSQ_ERR_INVAL - if the input parameters were invalid.
* MOSQ_ERR_NOMEM - if an out of memory condition occurred.
* MOSQ_ERR_NO_CONN - if the client isn't connected to a broker.
*/
libmosq_EXPORT int mosquitto_subscribe(struct mosquitto *mosq, int *mid, const char *sub, int qos); /*
* Function: mosquitto_unsubscribe
*
* Unsubscribe from a topic.
*
* Parameters:
* mosq - a valid mosquitto instance.
* mid - a pointer to an int. If not NULL, the function will set this to
* the message id of this particular message. This can be then used
* with the unsubscribe callback to determine when the message has been
* sent.
* sub - the unsubscription pattern.
*
* Returns:
* MOSQ_ERR_SUCCESS - on success.
* MOSQ_ERR_INVAL - if the input parameters were invalid.
* MOSQ_ERR_NOMEM - if an out of memory condition occurred.
* MOSQ_ERR_NO_CONN - if the client isn't connected to a broker.
*/
libmosq_EXPORT int mosquitto_unsubscribe(struct mosquitto *mosq, int *mid, const char *sub);

一般使用流程如下:

mosquitto_lib_init();
mosq=mosquitto_new(); mosquitto_connect_callback_set(); ----mosquitto_subscribe();
mosquitto_disconnect_callback_set();
mosquitto_message_callback_set(); ----接收解析消息 并推送mosquitto_publish() mosquitto_username_pw_set(mosq, "user", "pw");
mosquitto_connect();
mosquitto_loop(mosq, timeout, ); // 需要不断循环判断, 也可根据需要永远运行:mosquitto_loop_forever(mosq, timeout, 1) mosquitto_publish(); mosquitto_destroy(mosq);
mosquitto_lib_cleanup();

3. 应用

一般使用流程:

0. 依赖库安装

apt-get install openssl libssl-dev  uuid-dev

. 编译安装
make
make install
交叉编译:
CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ make WITH_SRV=no  WITH_UUID=no WITH_TLS=no WITH_DOCS=no WITH_WEBSOCKETS=no . 创建mosquitto用户
mosquitto默认以mosquitto用户启动
groupadd mosquitto
useradd -g mosquitto mosquitto . 配置文件修改
根据需求修改配置文件/etc/mosquitto/mosquitto.conf
一般不修改直接可用,本机所有IP都可达,外部访问本机IP可达。 . 启动
mosquitto -c /etc/mosquitto/mosquitto.conf -d . 测试
mosquitto_sub -t wang/ming
mosquitto_pub -m "hello"
mosquitto_pub -h 172.16.1.20 -p 1883 -t data_topic -m "hello_wang"
mosquitto_pub -h 172.16.1.20 -p 1883 -t data_topic -m "hello_wang"  -u admin -P 48e848df75c08d4c0ba75bee
服务器需要配置密码,客户端不用修改可直接采用密码上报

一个可参考配置文件如下:

 # Port to use for the default listener.
#port
port # Websockets support is currently disabled by default at compile time.
# Certificate based TLS may be used with websockets, except that
# only the cafile, certfile, keyfile and ciphers options are supported.
#protocol mqtt
listener
protocol websockets
listener
protocol websockets #cafile
#capath certfile /etc/cert/server.crt
keyfile /etc/cert/server.key # For example, setting "secure-" here would mean a client "secure-
# client" could connect but another with clientid "mqtt" couldn't.
#clientid_prefixes
clientid_prefixes ABC # Boolean value that determines whether clients that connect
# without providing a username are allowed to connect. If set to
# false then a password file should be created (see the
# password_file option) to control authenticated client access.
# Defaults to true.
#allow_anonymous true
allow_anonymous false # See the TLS client require_certificate and use_identity_as_username options
# for alternative authentication options.
#password_file
password_file /etc/mosquitto/pwfile

mosquitto是一个server broker,可直接运行测试客户端。

manpage上一个示例:

#include <stdio.h>
#include <mosquitto.h> void my_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
{
if(message->payloadlen){
printf("%s %s\n", message->topic, message->payload);
}else{
printf("%s (null)\n", message->topic);
}
fflush(stdout);
} void my_connect_callback(struct mosquitto *mosq, void *userdata, int result)
{
int i;
if(!result){
/* Subscribe to broker information topics on successful connect. */
mosquitto_subscribe(mosq, NULL, "$SYS/#", 2);
}else{
fprintf(stderr, "Connect failed\n");
}
} void my_subscribe_callback(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos)
{
int i; printf("Subscribed (mid: %d): %d", mid, granted_qos[0]);
for(i=1; i<qos_count; i++){
printf(", %d", granted_qos[i]);
}
printf("\n");
} void my_log_callback(struct mosquitto *mosq, void *userdata, int level, const char *str)
{
/* Pring all log messages regardless of level. */
printf("%s\n", str);
} int main(int argc, char *argv[])
{
int i;
char *host = "localhost";
int port = 1883;
int keepalive = 60;
bool clean_session = true;
struct mosquitto *mosq = NULL; mosquitto_lib_init();
mosq = mosquitto_new(NULL, clean_session, NULL);
if(!mosq){
fprintf(stderr, "Error: Out of memory.\n");
return 1;
}
mosquitto_log_callback_set(mosq, my_log_callback);
mosquitto_connect_callback_set(mosq, my_connect_callback);
mosquitto_message_callback_set(mosq, my_message_callback);
mosquitto_subscribe_callback_set(mosq, my_subscribe_callback); if(mosquitto_connect(mosq, host, port, keepalive)){
fprintf(stderr, "Unable to connect.\n");
return 1;
} mosquitto_loop_forever(mosq, -1, 1); mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
return 0;
}

自测程序

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <mosquitto.h> char peerid[] = "wangq";
char host[] = "127.0.0.1";
int port = ;
int keepalive = ;
bool clean_session = true;
struct mosquitto *mosq = NULL;
pthread_t pmosid = ; void my_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
{
if(message->payloadlen){
printf("====>recv:%s %s\n", message->topic, message->payload);
}else{
printf("%s (null)\n", message->topic);
} mosquitto_publish(mosq, NULL, "wang/result", sizeof("loveresult"), "loveresult", , false);
sleep(); fflush(stdout);
} void my_connect_callback(struct mosquitto *mosq, void *userdata, int result)
{
if(!result){
/* Subscribe to broker information topics on successful connect. */
//mosquitto_subscribe(mosq, NULL, "$SYS/broker/uptime", 2);
mosquitto_subscribe(mosq, NULL, "wang/hua", );
}else{
fprintf(stderr, "Connect failed\n");
}
} void my_subscribe_callback(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos)
{
int i; printf("Subscribed (mid: %d): %d", mid, granted_qos[]);
for(i=; i<qos_count; i++){
printf(", %d", granted_qos[i]);
}
printf("\n");
} void my_log_callback(struct mosquitto *mosq, void *userdata, int level, const char *str)
{
/* Pring all log messages regardless of level. */
printf("====>log:%s\n", str);
} void mos_init()
{
mosquitto_lib_init();
mosq = mosquitto_new(peerid, clean_session, NULL);
if(!mosq){
fprintf(stderr, "Error: Out of memory.\n");
exit(-);
}
mosquitto_log_callback_set(mosq, my_log_callback);
mosquitto_connect_callback_set(mosq, my_connect_callback);
mosquitto_message_callback_set(mosq, my_message_callback);
mosquitto_subscribe_callback_set(mosq, my_subscribe_callback);
mosquitto_will_set(mosq,"xiao/ming", sizeof("livewill"), "livewill", , false);
mosquitto_threaded_set(mosq, );
} void * pthread_mos(void *arg)
{
int toserver = -;
int timeout = ; while(toserver){
toserver = mosquitto_connect(mosq, host, port, keepalive);
if(toserver){
timeout++;
fprintf(stderr, "Unable to connect server [%d] times.\n", timeout);
if(timeout > ){
fprintf(stderr, "Unable to connect server, exit.\n" );
pthread_exit(NULL);
}
sleep();
}
} mosquitto_loop_forever(mosq, -, ); mosquitto_disconnect(mosq);
mosquitto_destroy(mosq);
mosquitto_lib_cleanup(); pthread_exit(NULL);
} int main(int argc, char *argv[])
{
int ret = ; mos_init(); ret = pthread_create(&pmosid, NULL, pthread_mos, NULL);
if(ret != ){
printf("create pthread mos error.\n");
exit(-);
}
pthread_detach(pmosid); while(){
mosquitto_publish(mosq, NULL, "wang/ming", sizeof("love"), "love", , false);
sleep();
} /*
mosquitto_loop_forever(mosq, -1, 1); while(1){
mosquitto_publish(mosq, NULL, "wang/qin/hua", sizeof("love"), "love", 2, false);
sleep(2);
}
*/
return ;
}

运行结果:

#./a.out
====>log:Client wangq sending CONNECT
====>log:Client wangq received CONNACK ()
====>log:Client wangq sending SUBSCRIBE (Mid: , Topic: wang/hua, QoS: )
====>log:Client wangq sending PUBLISH (d1, q2, r0, m1, 'wang/ming', ... ( bytes))
====>log:Client wangq received SUBACK
Subscribed (mid: ):
====>log:Client wangq received PUBREC (Mid: )
====>log:Client wangq sending PUBREL (Mid: )
====>log:Client wangq received PUBCOMP (Mid: )
====>log:Client wangq sending PUBLISH (d0, q2, r0, m3, 'wang/ming', ... ( bytes))
====>log:Client wangq received PUBREC (Mid: )
====>log:Client wangq sending PUBREL (Mid: )
====>log:Client wangq received PUBCOMP (Mid: )

订阅:

#mosquitto_sub -t wang/ming
love
love

will订阅:

#mosquitto_sub -t xiao/ming
livewill

参考:

1. MQTT协议规范 阿里云物理网

2. Mosquitto安装及使用

3. MQTT协议及EMQ应用

mosquitto简单应用的更多相关文章

  1. AsyncAPI 试用

    AsyncAPI 提供了类似openapi的代码生成,以下demo,来自官方,只是目前官方的generator有些问题以下 同时说明运行中的一些问题 环境准备 主要是安装依赖组件 npm instal ...

  2. MQTT协议及EMQ应用

    MQTT是基于TCP/IP协议栈构建的异步通信消息协议,是一种轻量级的发布/订阅信息传输协议.MQTT在时间和空间上,将消息发送者与接受者分离,可以在不可靠的网络环境中进行扩展.适用于设备硬件存储空间 ...

  3. Mosquitto pub/sub服务实现代码浅析-主体框架

    Mosquitto 是一个IBM 开源pub/sub订阅发布协议 MQTT 的一个单机版实现(目前也只有单机版),MQTT主打轻便,比较适用于移动设备等上面,花费流量少,解析代价低.相对于XMPP等来 ...

  4. Mosquitto搭建Android推送服务(三)Mosquitto集群搭建

    文章钢要: 1.进行双服务器搭建 2.进行多服务器搭建 一.Mosquitto的分布式集群部署 如果需要做并发量很大的时候就需要考虑做集群处理,但是我在查找资料的时候发现并不多,所以整理了一下,搭建简 ...

  5. Mosquitto搭建Android推送服务(二)Mosquitto简介及搭建

    文章钢要: 1.了解Mosquitto服务器 2.在Liunx中搭建Mosquitto服务器 3.设置Mosquitto集群 一.Mosquitto简介 一款实现了消息推送协议 MQTT v3.1 的 ...

  6. Mosquitto搭建Android推送服务(一)MQTT简介

    总体概要: MQTT系列文章分为4部分 1.MQTT简介 2.mosquitto服务器搭建 3.编写Mosquitto的可视化工具 4.使用Mosquitto完成Android推送服务 文章钢要: 对 ...

  7. Android开发笔记之《远程控制(MQTT|mosquitto) && (ProtocalBuffer | GRPC)》

    Android推送方案分析(MQTT/XMPP/GCM): http://www.open-open.com/lib/view/open1410848945601.htmlMQTT官网: http:/ ...

  8. Centos7-mqtt消息中间件mosquitto的安装和配置

    在以前发布的博客"菜鸟是如何打造智能家居系统的"文章最后我提到了使用MQTT协议作为云平台和设备之间的通信协议以达到消息传递的实时性,手机的消息推送也大多基于这种平台,首先搬来一段 ...

  9. 【转载】MQTT学习笔记——MQTT协议体验 Mosquitto安装和使用

    http://blog.csdn.net/xukai871105/article/details/39252653 0 前言     MQTT是IBM开发的一个即时通讯协议.MQTT是面向M2M和物联 ...

随机推荐

  1. Linux 4.10中两个新特性与我的一段故事

    今早5点半起来没有開始写文章,而是去西湾红树林连跑带走折腾了将近20公里.回来后就8点多了...洗了个澡之后坐稳当.開始写一段关于我的故事.        在2014年到2015年期间,我在负责研发一 ...

  2. 【转载并整理】mysql排序

    由于oracle中有排序函数,可以使用over的语句方便排序,但是mysql中没有 这里碰到几个mysql的概念:用户变量.系统变量.if语句.函数GROUP_CONCAT 1. 可以使用定义变量(@ ...

  3. ICDAR2015 数据处理及训练

    训练数据处理: 天池ICPR2018和MSRA_TD500两个数据集: 1)天池ICPR的数据集为网络图像,都是一些淘宝商家上传到淘宝的一些商品介绍图像,其标签方式参考了ICDAR2015的数据标签格 ...

  4. HBase中多Filter查询示例

    在Hbase查询中有时需要用到多个Filter关联的查询. 代码如下: ArrayList<Filter> listForFilters = new ArrayList<Filter ...

  5. ganglia安装 by frank

    作者是frank. 1.安装epelrpm -Uvh http://dl.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm2. ...

  6. iphone5 jail break

    dfu恢复恢复备份越狱afc2add删除2个文件,如果只有1个也没问题/var/mobile/Library/Caches/com.apple.mobile.installation.plist/va ...

  7. 【python】pycharm常用配置快速入门。

    俗话说,工欲善其事必先利其器.当我们想从事一门新的语言的时候,最重要的是熟悉其常用的编辑器的配置.刚好这两天在学习python,网上看到一篇比较好的文章,转载过来自己学习一下.感谢:https://s ...

  8. talend 连接mysql数据库没有权限

    使用talend连接一个mysql数据库,提示没有权限,最后发现mysql服务器的配置中只监听了127.0.0.1的端口,拒绝非本地的请求.通过将/etc/mysql/my.cnf中的bind_add ...

  9. IOS 设备备份文件详解 (二)

    这篇主要讲解如何解析Manifest.mbdb文件. 使用二进制工具打开这个文件,文件的头6个字节是固定的,相当于是文件的一种标识 后面的内容是一个一个的项,可以使用一个循环来读取文件,一个一个解析. ...

  10. Pycrypto与RSA密码技术笔记

    密码与通信 密码技术是一门历史悠久的技术.信息传播离不开加密与解密.密码技术的用途主要源于两个方面,加密/解密和签名/验签 在信息传播中,通常有发送者,接受者和窃听者三个角色.假设发送者Master想 ...