MQTT源码分析

本文详细解析了MQTT客户端的功能实现,包括连接服务器、创建线程、发布和订阅消息的过程,以及程序的分层结构。重点讨论了使用EclipseMosquitto和socketAPI构建高稳定、跨平台的客户端,展示了连接管理、数据包发送和内核线程监控的关键部分。
摘要由CSDN通过智能技术生成

目录

MQTT源码分析

1. MQTT客户端功能

2. 客户端软件如何实现

3. 程序分层

4. 情景分析

4.1 连接服务器

4.2 创建线程

4.3 发布消息

4.4 最复杂:订阅消息


MQTT源码分析

分析源码:mqttclient\test\emqx\test.c

参考资料:

1. MQTT客户端功能

MQTT通信模型示意图如下:

以"记者-电视台-观众"的模式来理解,客户端具体的流程是这样的:

  • 客户端1:观众打电话到电视台:connect

  • 客户端1:观众向电视台订阅"财经新闻": Subscribe 某个 Topic

  • 客户端2:记者打电话到电视台:connect

  • 客户端2:记者向电视台发布"财经新闻":Public某个Topic的某个Playload

  • 服务器:电视台向"订阅了财经新闻的观众"发布"某条消息":Public某个Playload给Subscriber

整个过程中,电视台和记者、电视台和观众直接的电话要保存连接状态,还要时不时确认一下:

  • 记者要时不时给电视台喊一声"喂":确保电视台还正常

  • 观众要时不时给电视台喊一声"喂":确保电视台还正常

2. 客户端软件如何实现

  • 连接服务器

  • 订阅:

    • 发布订阅请求,等待回应

    • 循环:读取Publish信息(得到订阅的信息),处理

  • 发布:

    • 发送数据包即可

  • PING

    • 循环:确保自己、对方还活着

    • mqtt_packet_handle > mqtt_keep_alive

需要一个循环!

3. 程序分层

至少可以分为3层:

  • 最上层:APP

  • 中间层:MQTT

  • 平台层:实现多线程、定时器、网卡收发数据

4. 情景分析

4.1 连接服务器

函数调用过程:

main
    client = mqtt_lease();
    mqtt_set_port(client, "1883");
    mqtt_set_host(client, "www.jiejie01.top");
​
    mqtt_connect(client);
        mqtt_connect_with_results(c);
            rc = network_init(c->mqtt_network, c->mqtt_host, c->mqtt_port, NULL);
            rc = network_connect(c->mqtt_network);
                    nettype_tcp_connect(n); 
                        platform_net_socket_connect

4.2 创建线程

调用过程:

main
    mqtt_connect(client);
        mqtt_connect_with_results(c);
            rc = network_init(c->mqtt_network, c->mqtt_host, c->mqtt_port, NULL);
            rc = network_connect(c->mqtt_network);
​
            /* send connect packet */
            if ((rc = mqtt_send_packet(c, len, &connect_timer)) != MQTT_SUCCESS_ERROR)
                goto exit;
​
            if (mqtt_wait_packet(c, CONNACK, &connect_timer) == CONNACK) {
            }
​
            /* connect success, and need init mqtt thread */
            c->mqtt_thread= platform_thread_init("mqtt_yield_thread", mqtt_yield_thread,c, ...);
 

4.3 发布消息

调用过程:

main
    res = pthread_create(&thread1, NULL, mqtt_publish_thread, client);
                mqtt_publish_thread
                    mqtt_publish(client, "topic1", &msg);
​
// 1. 构造消息
mqtt_message_t msg;
​
memset(&msg, 0, sizeof(msg));
msg.payload = (void *) buf;
msg.payloadlen = xxx;
​
mqtt_publish(client, "topic1", &msg);
    // 1.1 根据MQTT协议构造数据包
​
    // 1.2 根据平台相关的函数发送数据包
    mqtt_send_packet
        network_write
            nettype_tcp_write
                platform_net_socket_write_timeout

4.4 最复杂:订阅消息

消息何时到来?不知道!

所以,必定是某个内核线程不断查询网卡:

  • 读网卡数据

    • 得到数据的话就判断、处理

  • 21
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

热爱嵌入式的小佳同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值