Todos los productos
Search
Centro de documentos

:Ejemplo

Última actualización: Sep 07, 2026

Este tema describe cómo usar certificados X.509 para conectar dispositivos basados en MQTT . Para ello, se utiliza el archivo de código de ejemplo ./demos/mqtt_x509_auth_demo.c.

Contexto

Paso 1: Inicialización

  1. Agregue los archivos de encabezado.

    #include "aiot_state_api.h"
    #include "aiot_sysdep_api.h"
    #include "aiot_mqtt_api.h"
  2. Configure las dependencias subyacentes y la salida de registros.

        aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile);
        aiot_state_set_logcb(demo_state_logcb);
  3. Llame a aiot_mqtt_init para crear una instancia de cliente MQTT e inicializar los parámetros predeterminados.

        mqtt_handle = aiot_mqtt_init();
        if (mqtt_handle == NULL) {
            printf("aiot_mqtt_init failed\n");
            return -1;
        }

no heading

Paso 2: Configurar funciones

Llame a la operación aiot_mqtt_setopt para configurar los siguientes elementos:

  1. Set connection parameters.

  2. Configure a callback to obtain device identity information.

  3. Configure callbacks to monitor status and receive messages.

Para consultar más elementos de configuración, vea aiot_mqtt_option_t.

  1. Establezca los parámetros de conexión.

    • const char client_cert[] = {
          "-----BEGIN CERTIFICATE-----\r\n"
          "MIIDiDCCAnCgAwIBAgIIAJ3GD7c2860wDQYJKoZIhvcNAQELBQAwUzEoMCYGA1UE\r\n"
          ... 
          ...
          "v4aDacYavCH03JXKQ6zWpAwnwLcYrbW7XdhtDrqFCj+v6VJ6NDZaTGEW3/I=\r\n"
          "-----END CERTIFICATE-----\r\n"
      };
      
      const char client_private_key[] = {
      
          "-----BEGIN RSA PRIVATE KEY-----\r\n"
          "MIIEowIBAAKCAQEApyRaelm4b4sKOlqBywOIR4RIJrYEfNtYIAofMIkkwnClrqgh\r\n"
          ...    
          ...
          "mPw5JEAkNBy6wOWepJ9Tv1wY8yFEzV2dVsx3P93p5P3UdZb4M7i0\r\n"
          "-----END RSA PRIVATE KEY-----\r\n"
      };
          ...
      int main(int argc, char *argv[])
      {
          int32_t     res = STATE_SUCCESS;
          void       *mqtt_handle = NULL;
          char       *host = "x509.itls.cn-shanghai.aliyuncs.com";
      
          uint16_t    port = 1883; 
          aiot_sysdep_network_cred_t cred; 
      
          char *product_key       = "";
          char *device_name       = "";
          char *device_secret     = "";
      
          ...
          /* The security credential structure. To establish a TLS connection, specify the CA certificate in this structure. */
          aiot_sysdep_network_cred_t cred;
      
          /* Create a security credential for the SDK to establish a TLS connection. */
          memset(&cred, 0, sizeof(aiot_sysdep_network_cred_t));
          cred.option = AIOT_SYSDEP_NETWORK_CRED_SVRCERT_CA;  /* Verify the MQTT broker by using the RSA certificate. */
          cred.max_tls_fragment = 16384; /* The fragment can be up to 16 KB in length. Other optional values include 4 KB, 2 KB, 1 KB, and 0.5 KB. */
          cred.sni_enabled = 1;                               /* The Server Name Indicator (SNI) extension is supported when you establish a TLS connection. */
          cred.x509_server_cert = ali_ca_crt;                 /* The RSA root certificate that is used to verify the MQTT broker. */
          cred.x509_server_cert_len = strlen(ali_ca_crt);     /* The length of the RSA root certificate. */
      
          /* TODO: When you use an X.509 certificate for two-way authentication, you must add the following code to set a security credential. */
          cred.x509_client_cert = client_cert;
          cred.x509_client_cert_len = strlen(client_cert);
          cred.x509_client_privkey = client_private_key;
          cred.x509_client_privkey_len = strlen(client_private_key);
      
          /* Set the security credential of the connection. */
          aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_NETWORK_CRED, (void *)&cred);
      
          ...
      }
    • ParámetroEjemploDescripción
      client_cert[]
          "-----BEGIN CERTIFICATE-----\r\n"
          "MIIDiDCCAnCgAwIBAgIIAJ3GD7c2860wDQYJKoZIhvcNAQELBQAwUzEoMCYGA1UE\r\n"
          ... 
          ...
          "v4aDacYavCH03JXKQ6zWpAwnwLcYrbW7XdhtDrqFCj+v6VJ6NDZaTGEW3/I=\r\n"
          "-----END CERTIFICATE-----\r\n"
      La información del certificado X.509 del dispositivo.

      En la página Device Details de la consola de IoT Platform, haga clic en Download, junto a X.509 Certificate, para descargar la información del certificado. Después de descomprimir el archivo del certificado, reemplace el valor de este parámetro con la información del archivo .cer, siguiendo el formato del valor de ejemplo.

      La información del certificado consta de varias líneas de cadenas. Los puntos suspensivos (…) en el código de ejemplo indican las cadenas omitidas. Agregue " al principio y \r\n" al final de cada cadena.

      client_private_key[]
          "-----BEGIN RSA PRIVATE KEY-----\r\n"
          "MIIEowIBAAKCAQEApyRaelm4b4sKOlqBywOIR4RIJrYEfNtYIAofMIkkwnClrqgh\r\n"
          ... 
          ...
          "mPw5JEAkNBy6wOWepJ9Tv1wY8yFEzV2dVsx3P93p5P3UdZb4M7i0\r\n"
          "-----END RSA PRIVATE KEY-----\r\n"
      La clave privada del certificado X.509.

      En la página Device Details de la consola de IoT Platform, haga clic en Download, junto a X.509 Certificate, para descargar la información del certificado. Después de descomprimir el archivo del certificado, reemplace el valor de este parámetro con la información del archivo .key, siguiendo el formato del valor de ejemplo.

      La clave privada consta de varias líneas de cadenas. Los puntos suspensivos (…) en el código de ejemplo indican las cadenas omitidas. Agregue " al principio y \r\n" al final de cada cadena.

      hostx509.itls.cn-shanghai.aliyuncs.com Formato: x509.itls.${YourRegionId}.aliyuncs.com.

      Reemplace ${YourRegionId} con el ID de la región donde el dispositivo se conecta a IoT Platform. Para obtener más información, consulte Regions and zones.

      port1883El número de puerto.
      product_key""Si usa certificados X.509 para la autenticación, especifique una cadena vacía para cada uno de estos parámetros.
      device_name""
      device_secret""
  2. Configure un callback para obtener la información de identidad del dispositivo.

    Cuando un dispositivo usa un certificado X.509 para autenticarse y establece una conexión con IoT Platform, la plataforma le envía un mensaje que contiene un

    ProductKey

    y un

    DeviceName

    . Debe configurar un callback para recibir dicho mensaje. Este callback se invoca para guardar esos parámetros en una ubicación específica y utilizarlos más adelante.

    Personalice la función demo_get_device_info. En este ejemplo, el mensaje se analiza sintácticamente y se imprime.

    • 
      static void demo_get_device_info(const char *topic, uint16_t topic_len, const char *payload, uint32_t payload_len)
      {
          const char *target_topic = "/ext/auth/identity/response";
          char *p_product_key = NULL;
          uint32_t product_key_len = 0;
          char *p_device_name = NULL;
          uint32_t device_name_len = 0;
          int32_t res = STATE_SUCCESS;
      
          if (topic_len != strlen(target_topic) || memcmp(topic, target_topic, topic_len) != 0) {
              return;
          }
      
          /* TODO: The core_json_value operation in the SDK is specified as an example. 
      
                   You must replace the operation with an operation from a JSON parsing library such as cJSON to process payloads.
          */
          res = core_json_value(payload, payload_len, "productKey", strlen("productKey"), &p_product_key, &product_key_len);
          if (res < 0) {
              return;
          }
          res = core_json_value(payload, payload_len, "deviceName", strlen("deviceName"), &p_device_name, &device_name_len);
          if (res < 0) {
              return;
          }
      
          if (g_product_key == NULL) {
              g_product_key = malloc(product_key_len + 1);
              if (NULL == g_product_key) {
                  return;
              }
      
              memset(g_product_key, 0, product_key_len + 1);
              memcpy(g_product_key, p_product_key, product_key_len);
          }
          if (g_device_name == NULL) {
              g_device_name = malloc(device_name_len + 1);
              if (NULL == g_product_key) {
                  return;
              }
      
              memset(g_device_name, 0, device_name_len + 1);
              memcpy(g_device_name, p_device_name, device_name_len);
          }
      
          printf("device productKey: %s\r\n", g_product_key);
          printf("device deviceName: %s\r\n", g_device_name);
      }
    • Nota:

      IoT Platform utiliza el tema /ext/auth/identity/response para emitir un ProductKey y un DeviceName al dispositivo. Formato del Payload:

      {
          "productKey":"***",
          "deviceName":"***"
      }
  3. Configure el monitoreo de estado y los callbacks de mensajes.

    1. Configure la función de callback de monitoreo de estado.

      • Código de ejemplo:

         int main(int argc, char *argv[])
        {
            ...
            ...
        
            /* Configure the default MQTT message callback function. */
            aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_RECV_HANDLER, (void *)demo_mqtt_default_recv_handler);
            /* Configure the MQTT event callback function. */
            aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_EVENT_HANDLER, (void *)demo_mqtt_event_handler);
            ...
            ...
        }
                                      
      • Parámetros relacionados:

        Elemento de configuración

        Valor de ejemplo

        Descripción

        AIOT_MQTTOPT_RECV_HANDLER

        demo_mqtt_default_recv_handler

        Cuando se recibe un mensaje, se ejecuta la lógica de procesamiento correspondiente definida en esta función de callback.

        AIOT_MQTTOPT_EVENT_HANDLER

        demo_mqtt_event_handler

        Cuando cambia el estado de conexión del dispositivo, se ejecuta la lógica de procesamiento correspondiente definida en esta función de callback.

    2. Defina la función de callback de monitoreo de estado.

      Importante
      • No defina una lógica de manejo de eventos que consuma mucho tiempo, ya que puede bloquear el hilo de recepción de mensajes.

      • El estado de conexión puede cambiar debido a eventos como excepciones de red, reconexiones automáticas correctas y desconexiones.

      • Modifique el código en el marcador TODO para gestionar los cambios en el estado de conexión.

      /* This is an MQTT event callback function. This function is triggered when the device connects to, reconnects to, or disconnects from the network. For event definitions, see core/aiot_mqtt_api.h. */
      void demo_mqtt_event_handler(void *handle, const aiot_mqtt_event_t *event, void *userdata)
      {
          switch (event->type) {
              /* The aiot_mqtt_connect() function is called to establish a connection with the MQTT server. */
              case AIOT_MQTTEVT_CONNECT: {
                  printf("AIOT_MQTTEVT_CONNECT\n");
                  /* TODO: Handle the successful connection establishment of the SDK. Do not call long-running blocking functions here. */
              }
              break;
      
              /* The SDK is passively disconnected due to network issues and then automatically and successfully reconnects. */
              case AIOT_MQTTEVT_RECONNECT: {
                  printf("AIOT_MQTTEVT_RECONNECT\n");
                  /* TODO: Handle the successful reconnection of the SDK. Do not call long-running blocking functions here. */
              }
              break;
      
              /* The SDK is passively disconnected due to network issues. This can be caused by a read/write failure at the network layer or a failure to receive a heartbeat response from the server as expected. */
              case AIOT_MQTTEVT_DISCONNECT: {
                  char *cause = (event->data.disconnect == AIOT_MQTTDISCONNEVT_NETWORK_DISCONNECT) ? ("network disconnect") :
                                ("heartbeat disconnect");
                  printf("AIOT_MQTTEVT_DISCONNECT: %s\n", cause);
                  /* TODO: Handle the passive disconnection of the SDK. Do not call long-running blocking functions here. */
              }
              break;
      
              default: {
      
              }
          }
      }
                                      
    3. Defina la función de callback de recepción de mensajes.

      Importante
      • Evite definir una lógica de manejo de eventos que consuma mucho tiempo para no bloquear el hilo de recepción de mensajes.

      • Para procesar los mensajes recibidos, modifique el código en el marcador TODO.

      
      /* This is the default MQTT message callback function. This function is called when the SDK receives an MQTT message from the server and you have not configured a specific callback for it. */
      void demo_mqtt_default_recv_handler(void *handle, const aiot_mqtt_recv_t *packet, void *userdata)
      {
          switch (packet->type) {
              case AIOT_MQTTRECV_HEARTBEAT_RESPONSE: {
                  printf("heartbeat response\n");
                  /* TODO: Handle the server's response to the heartbeat. This is generally not required. */
              }
              break;
      
              case AIOT_MQTTRECV_SUB_ACK: {
                  printf("suback, res: -0x%04X, packet id: %d, max qos: %d\n",
                         -packet->data.sub_ack.res, packet->data.sub_ack.packet_id, packet->data.sub_ack.max_qos);
                  /* TODO: Handle the server's response to the subscription request. This is generally not required. */
              }
              break;
      
              case AIOT_MQTTRECV_PUB: {
                  printf("pub, qos: %d, topic: %.*s\n", packet->data.pub.qos, packet->data.pub.topic_len, packet->data.pub.topic);
                  printf("pub, payload: %.*s\n", packet->data.pub.payload_len, packet->data.pub.payload);
                  /* TODO: Handle the service message sent from the server. */
              }
              break;
      
              case AIOT_MQTTRECV_PUB_ACK: {
                  printf("puback, packet id: %d\n", packet->data.pub_ack.packet_id);
                  /* TODO: Handle the server's response to a reported message with QoS=1. This is generally not required. */
              }
              break;
      
              default: {
      
              }
          }
      }

no heading

Paso 3: Solicitar una conexión

Llame a la operación aiot_mqtt_connect para enviar una solicitud de autenticación y conexión a IoT Platform.

/* Establish an MQTT connection with IoT Platform. */  */
    res = aiot_mqtt_connect(mqtt_handle);
    if (res < STATE_SUCCESS) {
        /* Release resources of the MQTT instance if the MQTT connection fails to be established.  */
        aiot_mqtt_deinit(&mqtt_handle);
        printf("aiot_mqtt_connect failed: -0x%04X\n", -res);
        return -1;
    }

Paso 4: Iniciar el hilo de keepalive

Llame a la función aiot_mqtt_process para enviar mensajes de latido al servidor. Esta función mantiene una conexión persistente para el dispositivo y reenvía los mensajes no confirmados que tienen un nivel de calidad de servicio (QoS) de 1.

  1. Inicie el hilo de keepalive.

        res = pthread_create(&g_mqtt_process_thread, NULL, demo_mqtt_process_thread, mqtt_handle);
        if (res < 0) {
            printf("pthread_create demo_mqtt_process_thread failed: %d\n", res);
            return -1;
        }
  2. Establezca la función controladora del hilo de keepalive.

    void *demo_mqtt_process_thread(void *args)
    {
        int32_t res = STATE_SUCCESS;
    
        while (g_mqtt_process_thread_running) {
            res = aiot_mqtt_process(args);
            if (res == STATE_USER_INPUT_EXEC_DISABLED) {
                break;
            }
            sleep(1);
        }
        return NULL;
    }

Paso 5: Iniciar el hilo de recepción

Llame a aiot_mqtt_recv para recibir mensajes MQTT del servidor. La función de callback de mensajes procesa dichos mensajes. Si el dispositivo se desconecta, se reconecta automáticamente y activa la función de callback de eventos.

  1. Inicie el hilo de recepción.

    
        res = pthread_create(&g_mqtt_recv_thread, NULL, demo_mqtt_recv_thread, mqtt_handle);
        if (res < 0) {
            printf("pthread_create demo_mqtt_recv_thread failed: %d\n", res);
            return -1;
        }
                                        
  2. Establezca la función controladora del hilo de recepción.

    void *demo_mqtt_recv_thread(void *args)
    {
        int32_t res = STATE_SUCCESS;
    
        while (g_mqtt_recv_thread_running) {
            res = aiot_mqtt_recv(args);
            if (res < STATE_SUCCESS) {
                if (res == STATE_USER_INPUT_EXEC_DISABLED) {
                    break;
                }
                sleep(1);
            }
        }
        return NULL;
    }

Paso 6: Suscribirse a un tema

Llame a la operación aiot_mqtt_sub para suscribirse a un tema específico.

  • Código de ejemplo:

        {
            char *sub_topic = "/a18wP******/LightSwitch/user/get";
    
            res = aiot_mqtt_sub(mqtt_handle, sub_topic, NULL, 1, NULL);
            if (res < 0) {
                printf("aiot_mqtt_sub failed, res: -0x%04X\n", -res);
                return -1;
            }
        }
    Nota

    Una vez completada la configuración, elimine los símbolos de comentario del código correspondiente.

  • Parámetros relacionados:

    Parámetro

    Ejemplo

    Descripción

    sub_topic

    /a18wP/LightSwitch/user/get

    Un tema al que el dispositivo tiene permiso para suscribirse.

    • a18wP es el ProductKey del dispositivo.

    • LightSwitch es el DeviceName del dispositivo.

    Este ejemplo utiliza un tema personalizado predeterminado.

    El dispositivo recibe mensajes de IoT Platform a través de este tema.

    Para obtener más información sobre los temas, consulte What is a topic?.

Paso 7: Enviar un mensaje

Llame a aiot_mqtt_pub para enviar un mensaje a un tema específico.

  • Código de ejemplo:

         {
            char *pub_topic = "/a18wP******/LightSwitch/user/update";
            char *pub_payload = "{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}";
    
            res = aiot_mqtt_pub(mqtt_handle, pub_topic, (uint8_t *)pub_payload, (uint32_t)strlen(pub_payload), 0);
            if (res < 0) {
                printf("aiot_mqtt_sub failed, res: -0x%04X\n", -res);
                return -1;
            }
        }
    Nota

    Una vez completada la configuración, elimine los símbolos de comentario alrededor del código correspondiente.

  • Parámetros relacionados:

    Parámetro

    Ejemplo

    Descripción

    pub_topic

    /a18wP/LightSwitch/user/update

    Un tema en el que el dispositivo tiene permiso para publicar.

    • a18wP es el ProductKey del dispositivo.

    • LightSwitch es el DeviceName del dispositivo.

    El dispositivo envía mensajes a IoT Platform a través de este tema.

    Para obtener más información sobre los temas, consulte What is a topic?.

    pub_payload

    {\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}

    El contenido del mensaje reportado a IoT Platform.

    Dado que la categoría del tema del mensaje de ejemplo es personalizada, el formato de datos también puede serlo.

    Para obtener más información sobre los formatos de datos, consulte Data formats.

Después de que el dispositivo establezca la comunicación MQTT con IoT Platform, asegúrese de que el volumen de comunicación no supere el umbral.

  • Para obtener más información sobre los límites de comunicación, consulte Limits.

  • Si el volumen de comunicación supera el umbral, inicie sesión en la consola de IoT Platform para consultar los mensajes acumulados. Para obtener más información, consulte View and monitor consumer groups.

Paso 8: Desconectar

Nota

MQTT suele utilizarse en dispositivos que requieren una conexión persistente. Por lo tanto, el programa normalmente no llega a este punto.

En el programa de ejemplo, el hilo principal se encarga de configurar los parámetros y establecer la conexión. Una vez establecida la conexión, el hilo principal puede entrar en hibernación.

Llame a aiot_mqtt_disconnect para enviar un mensaje de desconexión a IoT Platform y desconectarse de la red.

    res = aiot_mqtt_disconnect(mqtt_handle);
    if (res < STATE_SUCCESS) {
        aiot_mqtt_deinit(&mqtt_handle);
        printf("aiot_mqtt_disconnect failed: -0x%04X\n", -res);
        return -1;
    }

Paso 9: Salir del programa

Llame a aiot_mqtt_deinit para destruir la instancia de cliente MQTT y liberar recursos.

    res = aiot_mqtt_deinit(&mqtt_handle);
    if (res < STATE_SUCCESS) {
        printf("aiot_mqtt_deinit failed: -0x%04X\n", -res);
        return -1;
    }

Qué hacer a continuación

  • . En este ejemplo, se genera el archivo ejecutable ./output/mqtt-x509-auth-demo.

    Para obtener más información, consulte Compile and run.

  • Runtime logs.