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. python IDE 集合

    python ruby等语言由于其小众和动态特性,缺少优良的IDE,本篇将介绍主要的python IDE. 1.python安装后自带有IDLE,简单方便,应该算是最简单的编辑环境了,但是过于简单,不 ...

  2. [转]IC行业的牛人

    转载的:   说来惭愧,我所了解的牛人也只是大学教授,工业界的高手了解的还太少,虽然我对教育界的牛人了解的也不多,但这里也要牢骚几句,论坛上的人好像只是认识Gray,Razavi,Allen,Lee, ...

  3. Android Studio 代码导航快捷键总结

    Android Studio 代码导航快捷键总结 这篇文章主要介绍了Android Studio 代码导航快捷键的相关资料,需要的朋友可以参考下   简评:作为一位 Android 开发者,Andro ...

  4. AliSQL 5.6.32 vs MySQL 5.7.15抢鲜测试

    摘要:    今天我们有幸抢鲜测试AliSQL,直接拿来和MySQL 5.7.15对比看看. AliSQL刚宣布开源,我就提交申请内测名额,节前收到开放内测邀请,于是第一时间进行了测试了解,希望能给大 ...

  5. HBase随机读写

    HDFS不太适合做大量的随机读应用,但HBASE却特别适合随机的读写 个人理解: 1.数据库一般都会有一层缓存,任何对数据的更改实际上是先更改内存中的数据.然后有异步的守护进程负责将脏页按照一定策略刷 ...

  6. Android 相关的资源

    源码分析: http://blog.csdn.net/luoshengyang/article/details/8923485 中文博客: 英文博客: https://github.com/andro ...

  7. ExtJs--05--给window组件加入功能条以及子组件获取上级或下级组件的属性和方法

    Ext.onReady(function(){ /** 1-- 给容器组件加入控制条 及 控制项 控制条 不同的方向有多种 tbar lbar rbar bbar fbar 2-- 依据组件本身拿到上 ...

  8. elasticsearch简介和倒排序索引介绍

    介绍 我们为什么要用搜索引擎?我们的所有数据在数据库里面都有,而且 Oracle.SQL Server 等数据库里也能提供查询检索或者聚类分析功能,直接通过数据库查询不就可以了吗?确实,我们大部分的查 ...

  9. linux:文件及文件夹管理

    http://blog.csdn.net/pipisorry/article/details/39854265 查看用户的信息 pika:~$id pikauid=1000(pika) gid=100 ...

  10. 调试web api的工具 谷歌插件 Restlet

    介绍 http://chromecj.com/productivity/2017-08/789.html