mosquitto简单应用
1. 简述
一款实现了消息推送协议 MQTT v3.1 的开源消息代理软件,提供轻量级的,支持可发布/可订阅的的消息推送模式,使设备对设备之间的短消息通信变得简单,比如现在应用广泛的低功耗传感器,手机、嵌入式计算机、微型控制器等移动设备。一个典型的应用案例就是 Andy Stanford-ClarkMosquitto(MQTT协议创始人之一)在家中实现的远程监控和自动化,并在 OggCamp 的演讲上,对MQTT协议进行详细阐述。
官网:
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
参考:
3. MQTT协议及EMQ应用
mosquitto简单应用的更多相关文章
- AsyncAPI 试用
AsyncAPI 提供了类似openapi的代码生成,以下demo,来自官方,只是目前官方的generator有些问题以下 同时说明运行中的一些问题 环境准备 主要是安装依赖组件 npm instal ...
- MQTT协议及EMQ应用
MQTT是基于TCP/IP协议栈构建的异步通信消息协议,是一种轻量级的发布/订阅信息传输协议.MQTT在时间和空间上,将消息发送者与接受者分离,可以在不可靠的网络环境中进行扩展.适用于设备硬件存储空间 ...
- Mosquitto pub/sub服务实现代码浅析-主体框架
Mosquitto 是一个IBM 开源pub/sub订阅发布协议 MQTT 的一个单机版实现(目前也只有单机版),MQTT主打轻便,比较适用于移动设备等上面,花费流量少,解析代价低.相对于XMPP等来 ...
- Mosquitto搭建Android推送服务(三)Mosquitto集群搭建
文章钢要: 1.进行双服务器搭建 2.进行多服务器搭建 一.Mosquitto的分布式集群部署 如果需要做并发量很大的时候就需要考虑做集群处理,但是我在查找资料的时候发现并不多,所以整理了一下,搭建简 ...
- Mosquitto搭建Android推送服务(二)Mosquitto简介及搭建
文章钢要: 1.了解Mosquitto服务器 2.在Liunx中搭建Mosquitto服务器 3.设置Mosquitto集群 一.Mosquitto简介 一款实现了消息推送协议 MQTT v3.1 的 ...
- Mosquitto搭建Android推送服务(一)MQTT简介
总体概要: MQTT系列文章分为4部分 1.MQTT简介 2.mosquitto服务器搭建 3.编写Mosquitto的可视化工具 4.使用Mosquitto完成Android推送服务 文章钢要: 对 ...
- Android开发笔记之《远程控制(MQTT|mosquitto) && (ProtocalBuffer | GRPC)》
Android推送方案分析(MQTT/XMPP/GCM): http://www.open-open.com/lib/view/open1410848945601.htmlMQTT官网: http:/ ...
- Centos7-mqtt消息中间件mosquitto的安装和配置
在以前发布的博客"菜鸟是如何打造智能家居系统的"文章最后我提到了使用MQTT协议作为云平台和设备之间的通信协议以达到消息传递的实时性,手机的消息推送也大多基于这种平台,首先搬来一段 ...
- 【转载】MQTT学习笔记——MQTT协议体验 Mosquitto安装和使用
http://blog.csdn.net/xukai871105/article/details/39252653 0 前言 MQTT是IBM开发的一个即时通讯协议.MQTT是面向M2M和物联 ...
随机推荐
- Python 文件 fileno() 方法
描述 Python 文件 fileno() 方法返回一个整型的文件描述符(file descriptor FD 整型),可用于底层操作系统的 I/O 操作. 语法 fileno() 方法语法如下: f ...
- 利用 T-sql 的从句 for xml path('') 实现多行合并到一行, 并带有分隔符
T-sql 有一个for xml path('')的从句能把多行结果合并到一行,并成为xml 格式 比如有一张表tb有两列,其格式和数据为: id value—————1 aa1 bb2 aaa2 b ...
- ldconfig命令
ldconfig是一个动态链接库管理命令 为了让动态链接库为系统所共享,还需运行动态链接库的管理命令--ldconfigldconfig 命令的用途,主要是在默认搜寻目录(/lib和/usr/lib) ...
- Android studio的一些常用快捷键
Alt+回车 导入包,自动修正 Ctrl+N 查找类 Ctrl+Shift+N 查找文件 Ctrl+Alt+L 格式化代码 Ctrl+Alt+O 优化导入的类和包 Alt+Insert 生成代码(如g ...
- WPF 控件事件的一个小坑…
最近想判断一下 Slider 是由鼠标点击而改变值,还是由程序内部代码改变的值,发现鼠标的各种事件比如 MouseDown.MouseUp.MouseLeftButtonDown 什么的,都没有任何反 ...
- 给Java开发人员的Play Framework(2.4)介绍 Part1:Play的优缺点以及适用场景
1. 关于这篇系列 这篇系列不是Play框架的Hello World,由于这样的文章网上已经有非常多. 这篇系列会首先结合实际代码介绍Play的特点以及适用场景.然后会有几篇文章介绍Play与Spri ...
- fastdfs 图片服务器 使用java端作为客户端上传图片
之前有说道搭建fastdfs作为图片服务器,但是没有说明如何真正在代码里调用,那么今天大致讲一下,如何使用java客户端进行上传 首先你得要有一个客户端,导入到eclipse中即可 git地址如下: ...
- 腾讯云服务器 - 定时备份MariaDB/MySQL
数据库数据备份尤为重要,而我们不会人工手动去备份,这样会很麻烦,我们都是通过服务器每日自定运行来做的,设置一个定时时间即可 首先我们看一下mysqldump这个文件的位置: 可以看到目录在 /usr/ ...
- 菜鸟学SSH(八)——Hibernate对象的三种状态
前面写了几篇关于SSH的博客,但不是Struts就是Spring,Hibernate还从来没写过呢.说好是SSH的,怎么可以光写那两个,而不写Hibernate呢对吧.今天就先说说Hibernate对 ...
- G1 Garbage Collector and Shenandoah
http://www.diva-portal.se/smash/get/diva2:754515/FULLTEXT01.pdf https://is.muni.cz/th/ifz8g/GarbageC ...