You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mosquitto C中如何正确发送与接收结构体作为消息负载?

结构体作为MQTT消息负载的正确实现(C语言+libmosquitto)

原代码的核心问题

  1. 发布端参数错误:mosquitto_publish的payload参数要求是void*类型,直接传入结构体变量defaults会导致类型不匹配,需传递结构体地址&defaults。
  2. 未初始化的垃圾数据:发布的结构体包含未赋值的uid数组,栈上的随机垃圾数据会被一并发送,可能引发接收端解析异常。
  3. 接收端内存复制错误:使用memset完全错误——该函数是用指定字节值填充内存,而非复制内存块,正确操作是用memcpy。
  4. 潜在跨平台对齐问题:默认结构体对齐规则可能导致不同平台上结构体大小、字段偏移不一致,跨设备传输时会出现解析错位。

修正后的完整实现

1. 定义带对齐控制的结构体

添加对齐指令,确保不同平台上结构体内存布局一致:

#pragma pack(push, 1)  // 强制1字节对齐,消除平台差异
typedef struct {
    char uid[100];
    unsigned int ka;
    unsigned int interval;
} Config;
#pragma pack(pop)

2. 发布端代码

// 初始化结构体,清空所有字段避免垃圾数据
Config defaults;
memset(&defaults, 0, sizeof(defaults));
// 填充需要发送的字段
defaults.ka = 60;
defaults.interval = 45;

// 调用mosquitto_publish,传递结构体地址作为payload
int ret = mosquitto_publish(
    mosq,
    NULL,
    "topic",
    sizeof(defaults),
    &defaults,  // 此处必须传入指针
    2,
    true
);
if (ret != MOSQ_ERR_SUCCESS) {
    syslog(LOG_ERR, "发布失败: %s", mosquitto_strerror(ret));
}

3. 接收端代码

syslog(LOG_INFO, "收到默认配置!");
// 先检查payload长度是否匹配结构体大小,避免内存越界
if (msg->payloadlen != sizeof(Config)) {
    syslog(LOG_WARNING, "配置消息长度不匹配,丢弃");
    return;
}

Config default_config;
// 用memcpy复制payload到结构体
memcpy(&default_config, msg->payload, sizeof(default_config));

// 处理配置
handleDefaultConfigAcquisition(&default_config);

额外注意事项

  • 若无需发送uid字段,建议单独定义用于传输的结构体(如ConfigPayload),仅包含ka和interval,减少传输数据量并避免不必要字段干扰。
  • 始终检查mosquitto_publish的返回值,及时处理发布失败场景。
  • 接收端必须验证消息长度,防止恶意或错误消息导致内存越界。

内容的提问来源于stack exchange,提问作者Sans the Medic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 00:42:35