Todos os produtos
Search
Central de documentação

:Exemplo

Última atualização: Jun 26, 2026

Este artigo descreve como usar certificados X.509 para conectar dispositivos baseados em MQTT . O arquivo de código de exemplo usado é o ./demos/mqtt_x509_auth_demo.c.

Informações básicas

Etapa 1: Inicialização

  1. Adicione os arquivos de cabeçalho.

    #include "aiot_state_api.h"
    #include "aiot_sysdep_api.h"
    #include "aiot_mqtt_api.h"
  2. Configure as dependências subjacentes e a saída de log.

        aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile);
        aiot_state_set_logcb(demo_state_logcb);
  3. Chame aiot_mqtt_init para criar uma instância de cliente MQTT e inicializar os parâmetros padrão.

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

no heading

Etapa 2: Configurar recursos

Chame aiot_mqtt_setopt para configurar os seguintes itens:

  1. Definir parâmetros de conexão.

  2. Configurar um callback para obter informações de identidade do dispositivo.

  3. Configurar callbacks para monitorar status e receber mensagens.

Para obter mais itens de configuração, consulte aiot_mqtt_option_t.

  1. Defina os parâmetros de conexão.

    • 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âmetroExemploDescrição
      client_cert[]
          "-----BEGIN CERTIFICATE-----\r\n"
          "MIIDiDCCAnCgAwIBAgIIAJ3GD7c2860wDQYJKoZIhvcNAQELBQAwUzEoMCYGA1UE\r\n"
          ... 
          ...
          "v4aDacYavCH03JXKQ6zWpAwnwLcYrbW7XdhtDrqFCj+v6VJ6NDZaTGEW3/I=\r\n"
          "-----END CERTIFICATE-----\r\n"
      Informações do certificado X.509 do dispositivo.

      Na página Device Details do console do IoT Platform, clique em Download ao lado de X.509 Certificate para baixar as informações do certificado. Após descompactar o arquivo de certificado, substitua o valor deste parâmetro pelas informações contidas no arquivo .cer, seguindo o formato do valor de exemplo.

      As informações do certificado consistem em várias linhas de strings. As reticências (…) no código de exemplo indicam strings omitidas. Adicione " no início e \r\n" no final de cada string.

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

      Na página Device Details do console do IoT Platform, clique em Download ao lado de X.509 Certificate para baixar as informações do certificado. Após descompactar o arquivo de certificado, substitua o valor deste parâmetro pelas informações contidas no arquivo .key, seguindo o formato do valor de exemplo.

      A chave privada consiste em várias linhas de strings. As reticências (…) no código de exemplo indicam strings omitidas. Adicione " no início e \r\n" no final de cada string.

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

      Substitua ${YourRegionId} pelo ID da região onde o dispositivo se conecta ao IoT Platform. Para obter mais informações, consulte Regiões e zonas.

      port1883Número da porta.
      product_key""Ao usar certificados X.509 para autenticação, especifique uma string vazia para cada um destes parâmetros.
      device_name""
      device_secret""
  2. Configure um callback para obter as informações de identidade do dispositivo.

    Após um dispositivo usar um certificado X.509 para autenticação e estabelecer uma conexão com o IoT Platform, a plataforma envia uma mensagem contendo o

    ProductKey

    e o

    DeviceName

    para o dispositivo. Configure um callback para receber essa mensagem. Esse callback salva esses parâmetros em um local especificado para uso posterior.

    Personalize a função demo_get_device_info. Neste exemplo, a mensagem é analisada e impressa.

    • 
      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:

      O IoT Platform usa o tópico /ext/auth/identity/response para emitir um ProductKey e um DeviceName para o dispositivo. Formato do Payload:

      {
          "productKey":"***",
          "deviceName":"***"
      }
  3. Configure os callbacks de monitoramento de status e de mensagens.

    1. Configure a função de callback de monitoramento de status.

      • Código de exemplo:

         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:

        Item de configuração

        Valor de exemplo

        Descrição

        AIOT_MQTTOPT_RECV_HANDLER

        demo_mqtt_default_recv_handler

        Executa a lógica de processamento definida nesta função de callback quando uma mensagem é recebida.

        AIOT_MQTTOPT_EVENT_HANDLER

        demo_mqtt_event_handler

        Aciona a lógica de processamento definida nesta função de callback sempre que o status da conexão do dispositivo muda.

    2. Defina a função de callback de monitoramento de status.

      Importante
      • Não defina lógicas de tratamento de eventos demoradas, pois elas podem bloquear a thread de recebimento de mensagens.

      • O status da conexão pode mudar devido a eventos como exceções de rede, reconexões automáticas bem-sucedidas e desconexões.

      • Modifique o código no marcador TODO para lidar com alterações no status da conexão.

      /* 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 a função de callback de recebimento de mensagens.

      Importante
      • Não defina lógicas de tratamento de eventos demoradas para evitar o bloqueio da thread de recebimento de mensagens.

      • Para processar as mensagens recebidas, modifique o código no 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

Etapa 3: Solicitar uma conexão

Chame aiot_mqtt_connect para enviar uma solicitação de autenticação e conexão ao 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;
    }

Etapa 4: Iniciar a thread keepalive

Chame a função aiot_mqtt_process para enviar mensagens de heartbeat ao servidor. Essa função mantém uma conexão persistente para o dispositivo e reenvia mensagens não confirmadas com nível de Qualidade de Serviço (QoS) 1.

  1. Inicie a thread 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. Defina a função handler da thread 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;
    }

Etapa 5: Iniciar a thread de recebimento

Chame aiot_mqtt_recv para receber mensagens MQTT do servidor. A função de callback de mensagens processa essas mensagens. Se o dispositivo for desconectado, ele se reconecta automaticamente e aciona a função de callback de eventos.

  1. Inicie a thread de recebimento.

    
        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. Defina a função handler da thread de recebimento.

    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;
    }

Etapa 6: Inscrever-se em um tópico

Chame aiot_mqtt_sub para inscrever-se em um tópico específico.

  • Código de exemplo:

        {
            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

    Após concluir a configuração, remova os símbolos de comentário do código relevante.

  • Parâmetros relacionados:

    Parâmetro

    Exemplo

    Descrição

    sub_topic

    /a18wP/LightSwitch/user/get

    Um tópico no qual o dispositivo tem permissão para se inscrever.

    • a18wP é o ProductKey do dispositivo.

    • LightSwitch é o DeviceName do dispositivo.

    Este exemplo usa um tópico personalizado padrão.

    O dispositivo recebe mensagens do IoT Platform por meio deste tópico.

    Para obter mais informações sobre tópicos, consulte O que é um tópico?.

Etapa 7: Enviar uma mensagem

Chame aiot_mqtt_pub para enviar uma mensagem a um tópico específico.

  • Código de exemplo:

         {
            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

    Após concluir a configuração, remova os símbolos de comentário ao redor do código relevante.

  • Parâmetros relacionados:

    Parâmetro

    Exemplo

    Descrição

    pub_topic

    /a18wP/LightSwitch/user/update

    Um tópico no qual o dispositivo tem permissão para publicar.

    • a18wP é o ProductKey do dispositivo.

    • LightSwitch é o DeviceName do dispositivo.

    O dispositivo envia mensagens ao IoT Platform por meio deste tópico.

    Para obter mais informações sobre tópicos, consulte O que é um tópico?.

    pub_payload

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

    Conteúdo da mensagem reportada ao IoT Platform.

    Como a categoria do tópico da mensagem de exemplo é personalizada, o formato dos dados também pode ser personalizado.

    Para obter mais informações sobre formatos de dados, consulte Formatos de dados.

Depois que o dispositivo estabelecer a comunicação MQTT com o IoT Platform, garanta que o volume de comunicação não exceda o limiar.

  • Para obter mais informações sobre limites de comunicação, consulte Limites.

  • Se o volume de comunicação ultrapassar o limiar, faça login no console do IoT Platform para visualizar mensagens acumuladas. Para obter mais detalhes, consulte Visualizar e monitorar grupos de consumidores.

Etapa 8: Desconectar

Nota

O protocolo MQTT é geralmente usado em dispositivos que exigem conexão persistente. Por isso, o programa normalmente não chega a este ponto.

No programa de exemplo, a thread principal configura parâmetros e estabelece a conexão. Após o estabelecimento da conexão, a thread principal pode entrar em hibernação.

Chame aiot_mqtt_disconnect para enviar uma mensagem de desconexão ao IoT Platform e encerrar a conexão de rede.

    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;
    }

Etapa 9: Sair do programa

Chame aiot_mqtt_deinit para destruir a instância do cliente MQTT e liberar recursos.

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

Próximos passos