我的目标是能够发送大约150MB的文件超过mosquitto.目前,这种转移的效率问题并不重要,只是为了了解这种转移是否可行.

MQTT规范提到消息负载限制为256MB,但我只能发送一个大小为4095KB的文件,仅此而已.发布器是用C蚊子库实现的,动态分配一个带有二进制数据的向量.发布程序不会遇到任何错误,但是在客户端发布数据后,如果发送的文件大于4065KB,则代理端不会出现发布通知,mosquitto_sub也不会收到任何消息,但发生的是来自代理的消息,发布客户端成功断开连接:

1711360340: New connection from 127.0.0.1:50002 on port 1883.
1711360340: New client connected from 127.0.0.1:50002 as auto-A51C5B5B-F445-5952-5EA5-49B12F2E614D (p2, c1, k5).
1711360340: No will message specified.
1711360340: Sending CONNACK to auto-A51C5B5B-F445-5952-5EA5-49B12F2E614D (0, 0)
1711360340: Client auto-A51C5B5B-F445-5952-5EA5-49B12F2E614D disconnected: Success.

真的有可能发送超过mosquitto个大文件吗?如果是,执行方面的最佳做法是什么?

编辑:删除文件源代码

#include <cstdio>
#include <mosquitto.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <memory>

struct mosquitto *mosq;

void publishImage(const char *topic, const char *image_path)
{
    std::ifstream fs(image_path, std::ios::in | std::ios::binary | std::ios::app);  
    std::unique_ptr<std::vector<uint8_t>> v_buf;
    void *msgPayload = nullptr;
    int msgPayloadLen;
    
    if (fs.good()) 
    {
        v_buf.reset(new std::vector<uint8_t>((std::istreambuf_iterator<char>(fs)), (std::istreambuf_iterator<char>())));
        fs.close();

        msgPayload = static_cast<void*>(v_buf.get()->data());
        msgPayloadLen = v_buf.get()->size();
    }

    if(msgPayload == nullptr)
    {
        fprintf(stderr, "image could not be copied to memory\n");
        return;
    }

    int rc = mosquitto_publish(mosq, NULL, topic, msgPayloadLen, msgPayload, 1, false);
    if (rc != MOSQ_ERR_SUCCESS)
    {
        fprintf(stderr, "mosquitto publish error: %s\n", mosquitto_strerror(rc));
    }

    return;
};

int main(int argc, const char* argv[])
{
    if (argc < 2)
    {
        fprintf(stderr, "Not enough input arguments!\nUsage: imageUpdater <topic> <path_to_image>\n");
        return 1;
    }

    const char *topic = argv[1];
    const char *pathToImage = argv[2];

    mosquitto_lib_init();

    mosq = mosquitto_new(NULL, true, NULL);
    if (mosq == NULL)
    {
        fprintf(stderr, "Error: Out of memory.\n");
        return 1;
    }

    int rc = mosquitto_connect(mosq,  "127.0.0.1", 1883, 5);
    if (rc != MOSQ_ERR_SUCCESS)
    {
        mosquitto_destroy(mosq);
        fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc));
        return 1;
    }
    else
    {
        printf("Connected!\n");
    }

    rc = mosquitto_loop_start(mosq);
    if (rc != MOSQ_ERR_SUCCESS)
    {
        mosquitto_destroy(mosq);
        fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc));
        return 1;
    }

    publishImage(topic, pathToImage);
    mosquitto_lib_cleanup();
    return 0;
}

EDIT2:成功发布的日志(log)输出(小文件)

1711376922: New client connected from 127.0.0.1:38426 as auto-33E25100-81EB-0583-E540-C73A5D29E267 (p2, c1, k5).
1711376922: No will message specified.
1711376922: Sending CONNACK to auto-33E25100-81EB-0583-E540-C73A5D29E267 (0, 0)
1711376922: Received PUBLISH from auto-33E25100-81EB-0583-E540-C73A5D29E267 (d0, q1, r0, m1, 'fota/update', ... (4192256 bytes))
1711376922: Sending PUBACK to auto-33E25100-81EB-0583-E540-C73A5D29E267 (m1, rc0)
1711376922: Client auto-33E25100-81EB-0583-E540-C73A5D29E267 closed its connection.

使用QOS0代替QOS1使传输更大的文件成为可能,但可靠性较低.10MB文件传输成功,但仅在第5次try 时才成功.实际再查,QOS1在多次try 后,也成功传输了10MB的文件.对于4000KB左右的文件,QOS0的可靠性不如QOS1.

推荐答案

这里正确的解决方案可能是在mosquitto_lib_cleanup()之前使用mosquitto_loop_stop()

正如文档所解释的,这应该等待未完成的消息发送后再退出.

这是线程化客户端接口的一部分. 调用这个函数一次以停止以前用mosquitto_loop_start创建的网络线程. 此调用将阻塞,直到网络线程结束.

Docs : https://mosquitto.org/api/files/mosquitto-h.html#mosquitto_loop_stop

C++相关问答推荐

C中的__attributor__((aligned(4),packed))与 struct 的用法

编译的时候g++通常会比GCC慢很多吗?

Win32API Wizzard97 PropSheet_SetWizButton不工作

向上强制转换C中的数值类型总是可逆的吗?

C在声明带有值的数组时,声明大小有用吗?

如果dim指定数组中的数据量,使用dim-1会不会潜在地导致丢失一个元素?

预先分配虚拟地址空间的区域

如何在STM8项目中导入STM8S/A标准外设库(ST VisualDeveloper)?

GTK函数调用将完全不相关的char* 值搞乱

S和查尔有什么不同[1]?

我在C中运行和调试时得到了不同的输出

运行时错误:在索引数组时加载类型为';char';`的空指针

静态初始化顺序失败是否适用于C语言?

为什么会出现此错误?二进制表达式的操作数无效

C程序printf在getchar while循环后不工作

关于不同C编译器中的__attribute__支持

为什么 int32_t 和 int16_t 在 printf 输出中具有相同的位数?

std::malloc/calloc/realloc/free 与纯 C 的 malloc/calloc/realloc/free 有什么不同

C Makefile - 如何避免重复提及文件名

我们可以在不违反标准的情况下向标准函数声明添加属性吗?