开发者社区> 问答> 正文

C 接入该如何进行?


注意:
本文给出的实例均基于 Eclipse Paho C SDK 实现,该 SDK 下载请参见 MQTT 接入准备。如使用其他第三方的客户端,请适当修改。

1. 资源申请


使用 MQ 提供的 MQTT 服务,首先需要核实应用中使用的 Topic 资源是否已经申请,如果没有请先去控制台申请 Topic,Group ID 等资源。
申请资源时需要根据需求选择对应的 Region,例如,MQTT 需要使用华北 2 的接入点,那么 Topic 等资源就在华北 2 申请,资源申请具体请参见 申请 MQ 资源
注意:MQTT 使用的多级子 Topic 不需要申请,代码里直接使用即可,没有限制。

2. C 客户端依赖


Paho MQTT C 客户端 SDK 从官网下载源码后,参考文档进行编译安装。可能需要安装以下开发库和工具。

  1. openssl:用于签名计算。
  2. cmake:用于编译示例程序,实际也可以根据习惯选用其他编译工具。


3. MQTT 收发消息


本段示例代码演示如何使用 C 客户端收发 MQTT 消息,其中编译工具使用CMake。
CMakeLists.txt 文件
  1. cmake_minimum_required(VERSION 3.7)
  2. project(mqttdemo)
  3. INCLUDE_DIRECTORIES(
  4.         .
  5.         ${CMAKE_SOURCE_DIR}/src
  6.         ${CMAKE_BINARY_DIR}
  7. )
  8. SET(CMAKE_BUILD_TYPE   "Debug")
  9. SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb")
  10. SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
  11. set(CMAKE_C_STANDARD 99)
  12. add_executable(mqttDemo mqttDemo.c)
  13. TARGET_LINK_LIBRARIES(mqttDemo crypto)
  14. TARGET_LINK_LIBRARIES(mqttDemo paho-mqtt3a)

收发消息程序:
  1. #include "MQTTAsync.h"
  2. #include <signal.h>
  3. #include <memory.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <openssl/hmac.h>
  7. #include <openssl/bio.h>
  8. volatile int connected = 0;
  9. char *topic;
  10. char *userName;
  11. char *passWord;
  12. int messageDeliveryComplete(void *context, MQTTAsync_token token) {
  13.     /* not expecting any messages */
  14.     printf("send message %d success\n", token);
  15.     return 1;
  16. }
  17. int messageArrived(void *context, char *topicName, int topicLen, MQTTAsync_message *m) {
  18.     /* not expecting any messages */
  19.     printf("recv message from %s ,body is %s\n", topicName, (char *) m->payload);
  20.     return 1;
  21. }
  22. void onConnectFailure(void *context, MQTTAsync_failureData *response) {
  23.     connected = 0;
  24.     printf("connect failed, rc %d\n", response ? response->code : -1);
  25.     MQTTAsync client = (MQTTAsync) context;
  26. }
  27. void onSubcribe(void *context, MQTTAsync_successData *response) {
  28.     printf("subscribe success \n");
  29. }
  30. void onConnect(void *context, MQTTAsync_successData *response) {
  31.     connected = 1;
  32.     printf("connect success \n");
  33.     MQTTAsync client = (MQTTAsync) context;
  34.     //do sub when connect success
  35.     MQTTAsync_responseOptions sub_opts = MQTTAsync_responseOptions_initializer;
  36.     sub_opts.onSuccess = onSubcribe;
  37.     int rc = 0;
  38.     if ((rc = MQTTAsync_subscribe(client, topic, 1, ⊂_opts)) != MQTTASYNC_SUCCESS) {
  39.         printf("Failed to subscribe, return code %d\n", rc);
  40.     }
  41. }
  42. void onDisconnect(void *context, MQTTAsync_successData *response) {
  43.     connected = 0;
  44.     printf("connect lost \n");
  45. }
  46. void onPublishFailure(void *context, MQTTAsync_failureData *response) {
  47.     printf("Publish failed, rc %d\n", response ? -1 : response->code);
  48. }
  49. int success = 0;
  50. void onPublish(void *context, MQTTAsync_successData *response) {
  51.     printf("send success %d\n", ++success);
  52. }
  53. void connectionLost(void *context, char *cause) {
  54.     connected = 0;
  55.     MQTTAsync client = (MQTTAsync) context;
  56.     MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
  57.     int rc = 0;
  58.     printf("Connecting\n");
  59.     conn_opts.keepAliveInterval = 10;
  60.     conn_opts.cleansession = 1;
  61.     conn_opts.username = userName;
  62.     conn_opts.password = passWord;
  63.     conn_opts.onSuccess = onConnect;
  64.     conn_opts.onFailure = onConnectFailure;
  65.     conn_opts.context = client;
  66.     conn_opts.ssl = NULL;
  67.     if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) {
  68.         printf("Failed to start connect, return code %d\n", rc);
  69.         exit(EXIT_FAILURE);
  70.     }
  71. }
  72. int main(int argc, char **argv) {
  73.     MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
  74.     MQTTAsync client;
  75.     //MQTT使用的Topic,其中第一级父Topic需要在MQ控制台先申请
  76.     topic = "XXXXX";
  77.       //MQTT的接入域名,在MQ控制台购买付费实例后即分配该域名
  78.     char *host = "XXX.mqtt.aliyuncs.com";
  79.     //MQTT客户端分组Id,需要先在MQ控制台申请
  80.     char *groupId = "GID_XXXXXX";
  81.     //MQTT客户端设备Id,用户自行生成,需要保证对于所有TCP连接全局唯一
  82.     char *deviceId = "XXXXXXX";
  83.     //帐号AK
  84.     char *accessKey = "XXXXXXX";
  85.     //帐号SK
  86.     char *secretKey = "XXXXXXX";
  87.     //服务端口,使用MQTT协议时设置1883,其他协议参考文档选择合适端口
  88.     int port = 1883;
  89.     //QoS,消息传输级别,参考文档选择合适的值
  90.     int qos = 1;
  91.     //cleanSession,是否设置持久会话,如果需要离线消息则cleanSession必须是false,QoS必须是1
  92.     int cleanSession = 0;
  93.     int rc = 0;
  94.     char tempData[100];
  95.     int len = 0;
  96.     HMAC(EVP_sha1(), secretKey, strlen(secretKey), groupId, strlen(groupId), tempData, &len);
  97.     char resultData[100];
  98.     int passWordLen = EVP_EncodeBlock((unsigned char *) resultData, tempData, len);
  99.     resultData[passWordLen] = '\0';
  100.     printf("passWord is %s", resultData);
  101.     userName = accessKey;
  102.     passWord = resultData;
  103.     //1.create client
  104.     MQTTAsync_createOptions create_opts = MQTTAsync_createOptions_initializer;
  105.     create_opts.sendWhileDisconnected = 0;
  106.     create_opts.maxBufferedMessages = 10;
  107.     char url[100];
  108.     sprintf(url, "%s:%d", host, port);
  109.     char clientIdUrl[64];
  110.     sprintf(clientIdUrl, "%s@@@%s", groupId, deviceId);
  111.     rc = MQTTAsync_createWithOptions(&client, url, clientIdUrl, MQTTCLIENT_PERSISTENCE_NONE, NULL, &create_opts);
  112.     rc = MQTTAsync_setCallbacks(client, client, connectionLost, messageArrived, NULL);
  113.     //2.connect to server
  114.     MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
  115.     conn_opts.keepAliveInterval = 90;
  116.     conn_opts.cleansession = cleanSession;
  117.     conn_opts.username = userName;
  118.     conn_opts.password = passWord;
  119.     conn_opts.onSuccess = onConnect;
  120.     conn_opts.onFailure = onConnectFailure;
  121.     conn_opts.context = client;
  122.     conn_opts.ssl = NULL;
  123.     conn_opts.automaticReconnect = 1;
  124.     conn_opts.connectTimeout = 3;
  125.     if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) {
  126.         printf("Failed to start connect, return code %d\n", rc);
  127.         exit(EXIT_FAILURE);
  128.     }
  129.     //3.publish msg
  130.     MQTTAsync_responseOptions pub_opts = MQTTAsync_responseOptions_initializer;
  131.     pub_opts.onSuccess = onPublish;
  132.     pub_opts.onFailure = onPublishFailure;
  133.     for (int i = 0; i < 1000; i++) {
  134.         do {
  135.             char data[100];
  136.             sprintf(data, "hello mqtt demo");
  137.             rc = MQTTAsync_send(client, topic, strlen(data), data, qos, 0, &pub_opts);
  138.             sleep(1);
  139.         } while (rc != MQTTASYNC_SUCCESS);
  140.     }
  141.     sleep(1000);
  142.     disc_opts.onSuccess = onDisconnect;
  143.     if ((rc = MQTTAsync_disconnect(client, &disc_opts)) != MQTTASYNC_SUCCESS) {
  144.         printf("Failed to start disconnect, return code %d\n", rc);
  145.         exit(EXIT_FAILURE);
  146.     }
  147.     while (connected)
  148.         sleep(1);
  149.     MQTTAsync_destroy(&client);
  150.     return EXIT_SUCCESS;
  151. }

展开
收起
猫饭先生 2017-10-27 11:05:05 2383 0
0 条回答
写回答
取消 提交回答
问答排行榜
最热
最新

相关电子书

更多
超融合网关和软硬件网关编排平台 立即下载
打造基于阿里云物联网平台的业务模型 立即下载
娃哈哈:从网络上云开启云端之路 立即下载