如果您在生产设备时还未明确设备需要连接的服务器站点,那么您的设备可以通过bootstrap服务器获取物联网控制台指定设备应该连接的国家或地区的站点,然后建立连接。
背景说明

如上图流程所示,使用C-SDK中的Bootstrap功能,可查询到设备应该连接的阿里云站点信息。
- Bootstrap服务目前仅通过
HTTPS
方式提供。 - 建立HTTPS连接时,TLS层的安全连接类型必须为证书方式,也即
AIOT_SYSDEP_NETWORK_CRED_SVRCERT_CA
。
API列表
以下是完整的Bootstrap部分API列表及简要说明 (详见components/bootstrap/aiot_bootstrap_api.h
)。
接口名 | 说明 |
---|---|
aiot_bootstrap_init | 初始化bootstrap实例并设置默认参数。 |
aiot_bootstrap_setopt | 配置bootstrap实例, 详见Bootstrap选项配置说明。 |
aiot_bootstrap_deinit | 释放bootstrap实例句柄的资源。 |
aiot_bootstrap_send_request | 向bootstrap服务器发送请求。 |
aiot_bootstrap_recv | 从bootstrap服务器接收应答。 |
例程讲解
现对照demos/bootstrap_basic_demo.c
例程, 分步骤讲解如何使用API。

这个例程演示了用SDK配置Bootstrap会话实例的参数, 并发起请求和接收应答, 之后
- 如果接收应答失败了, 销毁实例, 回收资源, 结束程序退出。
- 如果接收应答成功, 在
demo_bootstrap_recv_handler()
的应答处理回调函数中, 演示解析获取服务端应答的内容
需要用户关注或修改的部分, 已用 TODO
在注释中标明。
- 设置设备证书
例程使用的设备证书是公用的, 所以应用于实际业务时, 请替换如下的
TODO
部分, 传入用户自己真实的设备证书。/* TODO: 替换为自己设备的producKey和deviceName */ char *product_key = "a13FNXXXXXX"; char *device_name = "bootstrap_basic_demo";
- 进入程序入口, 给SDK配置全局的底层依赖和日志回调
底层依赖描述了硬件平台的资源使用方式, 比如怎样获取时钟, 分配内存等, 日志回调是用户的函数, SDK有log输出的时候会进入这个函数。
int main(int argc, char *argv[]) { ... ... /* 配置SDK的底层依赖 */ aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile); /* 配置SDK的日志输出 */ aiot_state_set_logcb(demo_state_logcb);
- 给Bootstrap会话配置参数
这些连接参数包括如何建立TLS连接, 服务器地址在哪, 连接后的数据及事件回调函数是什么等等。
/* 创建1个Bootstrap会话实例并内部初始化默认参数 */ bootstrap_handle = aiot_bootstrap_init(); /* 配置Bootstrap会话实例 * * 配置项详细说明可参考: http://gaic.alicdn.com/ztms/linkkit/html/aiot__bootstrap__api_8h.html#a9cc177610fa0842f8287ed4fa438d56d * */ aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_HOST, (void *)host); aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_PORT, (void *)&port); aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_PRODUCT_KEY, (void *)product_key); aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_DEVICE_NAME, (void *)device_name); aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_NETWORK_CRED, (void *)&cred); aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_RECV_HANDLER, (void *)demo_bootstrap_recv_handler); aiot_bootstrap_setopt(bootstrap_handle, AIOT_BOOTSTRAPOPT_USERDATA, (void *)&demo_info); ... ...
- 向服务器发送服务请求
使用
aiot_bootstrap_send_request()
接口, 以上面设置的参数, 向Bootstrap服务器发起服务请求。/* 发送Bootstrap服务请求 */ res = aiot_bootstrap_send_request(bootstrap_handle); if (res < STATE_SUCCESS) { printf("aiot_bootstrap_send_request failed, res: -0x%04X\n", -res); return -1; }
以下日志就对应被发送的服务请求。
[1580994365.099][LK-040D] < HTTP/1.1 200 OK [1580994365.099][LK-040D] < Server: Tengine [1580994365.099][LK-040D] < Date: Thu, 06 Feb 2020 13:06:05 GMT [1580994365.099][LK-040D] < Content-Type: text/xml [1580994365.099][LK-040D] < Content-Length: 129 [1580994365.099][LK-040D] < Connection: keep-alive [1580994365.099][LK-040D] < [LK-040E] < 7B 22 63 6F 64 65 22 3A 32 30 30 2C 22 64 61 74 | {"code":200,"dat [LK-040E] < 61 22 3A 7B 22 72 65 73 6F 75 72 63 65 73 22 3A | a":{"resources": [LK-040E] < 7B 22 6D 71 74 74 22 3A 7B 22 68 6F 73 74 22 3A | {"mqtt":{"host": [LK-040E] < 22 70 75 62 6C 69 63 2E 69 6F 74 2D 61 73 2D 6D | "public.iot-as-m [LK-040E] < 71 74 74 2E 63 6E 2D 73 68 61 6E 67 68 61 69 2E | qtt.cn-shanghai. [LK-040E] < 61 6C 69 79 75 6E 63 73 2E 63 6F 6D 22 2C 22 70 | aliyuncs.com","p [LK-040E] < 6F 72 74 22 3A 31 38 38 33 7D 7D 7D 2C 22 6D 65 | ort":1883}}},"me [LK-040E] < 73 73 61 67 65 22 3A 22 73 75 63 63 65 73 73 22 | ssage":"success" [LK-040E] < 7D | }
- 请求发送成功后, 尝试接收服务应答
使用
aiot_bootstrap_recv()
接口, 以上面设置的参数, 从Bootstrap服务器接收服务应答。/* 接收Bootstrap服务应答 */ res = aiot_bootstrap_recv(bootstrap_handle); if (res < STATE_SUCCESS) { printf("aiot_bootstrap_recv failed, res: -0x%04X\n", -res); return -1; }
以下日志对应的是被成功接收到的服务应答。
[1580829319.044][LK-040D] < HTTP/1.1 200 OK [1580829319.044][LK-040D] < Server: Tengine [1580829319.044][LK-040D] < Date: Tue, 04 Feb 2020 15:15:19 GMT [1580829319.044][LK-040D] < Content-Type: text/xml [1580829319.044][LK-040D] < Content-Length: 132 [1580829319.044][LK-040D] < Connection: keep-alive [1580829319.044][LK-040D] < [LK-040E] < 7B 22 63 6F 64 65 22 3A 32 30 30 2C 22 64 61 74 | {"code":200,"dat [LK-040E] < 61 22 3A 7B 22 72 65 73 6F 75 72 63 65 73 22 3A | a":{"resources": [LK-040E] < 7B 22 6D 71 74 74 22 3A 7B 22 68 6F 73 74 22 3A | {"mqtt":{"host": [LK-040E] < 22 70 75 62 6C 69 63 2E 69 6F 74 2D 61 73 2D 6D | "public.iot-as-m [LK-040E] < 71 74 74 2E 61 70 2D 73 6F 75 74 68 65 61 73 74 | qtt.ap-southeast [LK-040E] < 2D 31 2E 61 6C 69 79 75 6E 63 73 2E 63 6F 6D 22 | -1.aliyuncs.com" [LK-040E] < 2C 22 70 6F 72 74 22 3A 31 38 38 33 7D 7D 7D 2C | ,"port":1883}}}, [LK-040E] < 22 6D 65 73 73 61 67 65 22 3A 22 73 75 63 63 65 | "message":"succe [LK-040E] < 73 73 22 7D | ss"}
- 应答接收成功后, 在回调函数中解析应答内容
之前已经用
AIOT_BOOTSTRAPOPT_RECV_HANDLER
选项设置了, SDK收到应答时应进入的数据处理函数是demo_bootstrap_recv_handler()
。/* Bootstrap接收消息处理回调, 当SDK从服务器收到Bootstrap消息时被调用 */ void demo_bootstrap_recv_handler(void *handle, const aiot_bootstrap_recv_t *packet, void *userdata) { demo_info_t *demo_info = (demo_info_t *)userdata; switch (packet->type) { case AIOT_BOOTSTRAPRECV_STATUS_CODE: { demo_info->code = packet->data.status_code.code; } break; case AIOT_BOOTSTRAPRECV_CONNECTION_INFO: { demo_info->host = malloc(strlen(packet->data.connection_info.host) + 1); if (demo_info->host != NULL) { memset(demo_info->host, 0, strlen(packet->data.connection_info.host) + 1); /* TODO: 回调中需要将packet指向的空间内容复制保存好, 因为回调返回后, 这些空间就会被SDK释放 */ memcpy(demo_info->host, packet->data.connection_info.host, strlen(packet->data.connection_info.host)); demo_info->port = packet->data.connection_info.port; } } break; default: { } break; } }
Bootstrap服务应答已经被储存在回调函数的入参
packet
中, 在回调中需要将它的内容复制到demo_info
, 因为回调返回后, SDK就要将相关的内存空间释放掉了。 - 回到主流程, 打印服务应答的消息内容
aiot_bootstrap_recv()
接口返回后(其中经过了触发并执行demo_bootstrap_recv_handler()
), 服务器应答内容已被保存, 将它们打印出来。/* 把服务应答中的MQTT域名地址和端口号打印出来 */ if (demo_info.host != NULL) { printf("host: %s, port: %d\n", demo_info.host, demo_info.port); /* TODO: 可以保存host和port的内容, 后续用于建立MQTT连接 */ free(demo_info.host); }
实际的业务使用中,应答内容自然不只是被打印出来,对其中的MQTT服务器域名地址和端口,一般会被保存,然后传给SDK的MQTT接口, 用于建立MQTT长连接。
- 销毁会话实例, 释放资源退出
Bootstrap的主要功能:获取MQTT连接信息(域名+端口)已经演示完毕,流程到这里就清理资源,正常退出了。
/* 销毁Bootstrap会话实例 */ aiot_bootstrap_deinit(&bootstrap_handle);
在文档使用中是否遇到以下问题
更多建议
匿名提交