采用MQTT over TLS来加密MQTT消息,编译时报如下错误:
Failed to create client, return code -14
MQTTClient_create failed: Invalid protocol scheme
排查问题原因如下:
问题一:
安装paho mqtt c库时,需要指定启动SSL编译,通过在CMakeList.txt中查看:
## build options
option(PAHO_WITH_SSL "Flag that defines whether to build ssl-enabled binaries too. " FALSE)
可以发现,默认是SSL功能是关闭的!
安装 Paho MQTT C库步骤如下:
1、下载 Paho MQTT C 源码
git clone https://github.com/eclipse/paho.mqtt.c.git
cd paho.mqtt.c
git checkout v1.3.12 # 使用稳定版本(可选)
2、编译安装(启用 SSL)
mkdir build
cd build
# 配置(启用SSL)
cmake -DPAHO_WITH_SSL=TRUE \
-DPAHO_BUILD_SHARED=TRUE \
-DPAHO_BUILD_STATIC=TRUE \
-DCMAKE_INSTALL_PREFIX=/usr/local ..
# 编译并安装
make -j$(nproc)
sudo make install
# 更新动态库链接
sudo ldconfig
3、验证安装
检查生成的库文件:
ls /usr/local/lib/libpaho-mqtt3*
应看到包含 SSL 的库文件
libpaho-mqtt3as.so # 异步SSL库
libpaho-mqtt3cs.so # 同步SSL库
问题二:
编译时,启用SSL功能需要使用-lpaho-mqtt3cs
而非-lpaho-mqtt3c库
代码举例:
/*
* @Descripttion:
* @version:
* @Author: 输入自己姓名
* @Date: 2025-04-01 14:55:45
* @LastEditors: 输入自己姓名
* @LastEditTime: 2025-04-02 17:10:25
*/
#include <stdio.h>
#include <MQTTClient.h>
#include "cjson/cJSON.h"
#define ADDRESS "mqtts://localhost:8883" // TLS 端口通常为 8883
//#define ADDRESS "mqtt://localhost:1883" // TLS 端口通常为 8883
//#define ADDRESS "localhost"
#define CLIENT_ID "TLS_Client_Example"
#define TOPIC "subtest"
#define QOS 1
// TLS 配置参数
#define CA_CERT "/home/wuzuhan/code/0402cert/ca.crt" // CA 证书路径
#define CLIENT_CERT "/home/wuzuhan/code/0402cert/client.crt" // 客户端证书路径
#define PRIVATE_KEY "/home/wuzuhan/code/0402cert/client.key" // 客户端私钥路径
int main(int argc, char* argv[]) {
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_SSLOptions ssl_opts = MQTTClient_SSLOptions_initializer;
// 配置 TLS 参数
ssl_opts.enableServerCertAuth = 1; // 启用服务端证书验证
//ssl_opts.SSLVersion = MQTTCLIENT_SSL_VERSION_TLS1_2; // 指定TLS版本(如TLS 1.2)
//ssl_opts.CAList = CA_CERT; // 指定 CA 证书路径
ssl_opts.keyStore = CLIENT_CERT; // 客户端证书路径
ssl_opts.trustStore = CA_CERT; // 信任的 CA 证书路径
ssl_opts.privateKey = PRIVATE_KEY; // 客户端私钥路径
//ssl_opts.keyStorePassword = "your_key_password"; // 私钥密码(如有)
//ssl.cipherSuite = "TLS_RSA_WITH_AES_256_CBC_SHA"; // 加密套件(可选)
// 将 TLS 配置添加到连接选项
conn_opts.ssl = &ssl_opts;
// 连接选项设置
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
// 创建客户端(TLS 需要特殊配置)
int rc;
if ((rc = MQTTClient_create(&client, ADDRESS, CLIENT_ID, MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to create client, return code %d\n", rc);
printf("MQTTClient_create failed: %s\n", MQTTClient_strerror(rc));
return 1;
}
// 连接到 Broker
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) {
printf("Failed to connect: %d\n", rc);
printf("MQTTClient_create failed: %s\n", MQTTClient_strerror(rc));
MQTTClient_destroy(&client);
return 1;
}
// 订阅主题(可选)
MQTTClient_subscribe(client, TOPIC, QOS);
// 创建 JSON 对象
cJSON *root = cJSON_CreateObject();
cJSON_AddNumberToObject(root, "temperature", 25.5);
cJSON_AddNumberToObject(root, "humidity", 60);
cJSON_AddStringToObject(root, "device_id", "SENSOR_001");
// 将 JSON 对象转换为字符串
char *json_str = cJSON_Print(root);
if (!json_str) {
printf("Failed to print JSON\n");
cJSON_Delete(root);
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return 1;
}
// 发布消息(可选)
MQTTClient_message pubmsg = MQTTClient_message_initializer;
//pubmsg.payload = (void*)"Hello MQTT over TLS!";
pubmsg.payload = json_str;
pubmsg.payloadlen = strlen((char*)pubmsg.payload) + 1;
pubmsg.qos = QOS;
MQTTClient_publishMessage(client, TOPIC, &pubmsg, NULL);
// 等待消息(可选)
printf("Press any key to exit...\n");
getchar();
// 断开连接并清理资源
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return 0;
}
编译并运行:
gcc -o mqtt_over_tls mqtt_over_tls.c -lpaho-mqtt3cs -lcjson