【0x0012】HCI_Delete_Stored_Link_Key命令详解
目录
一、命令参数
二、命令格式及参数
2.1. HCI_Delete_Stored_Link_Key 命令格式
2.2. BD_ADDR
2.3. Delete_All
三、生成事件及参数
3.1. HCI_Command_Complete事件
3.2. Status
3.3. Num_Keys_Deleted
四、命令执行流程
4.1. 命令发送阶段
4.2. 控制器处理阶段
4.3. 命令完成反馈阶段
4.4. 主机处理反馈阶段
4.5. 示例代码
五、应用场景
六、注意事项
6.1. 确认删除对象
6.2. 设备状态与连接
6.3. 命令参数与执行
6.4. 并发操作与状态管理
6.5. 安全与隐私
6.6. 兼容性与版本
HCI_Delete_Stored_Link_Key
命令是用于删除蓝牙BR/EDR(Basic Rate/Enhanced Data Rate)控制器(蓝牙芯片)中存储的一个或多个链路密钥(Link Keys)的命令。Link key是两个蓝牙设备之间共享的密钥,用于确保两设备间的安全通信。蓝牙BR/EDR控制器可以存储有限数量的与其他BR/EDR设备相关联的链路密钥。
一、命令参数
HCI_Delete_Stored_Link_Key
命令允许用户删除存储在BR/EDR控制器中的一个或多个链路密钥。对于管理存储空间和隐私保护非常重要。
- 删除逻辑:
- 如果指定删除的链路密钥当前正在用于连接,则该链路密钥会立即从存储中标记为删除,但只有在所有使用该密钥的连接断开后,才会被完全删除。
- 如果链路密钥未被使用,则会被立即完全删除。
- 命令完成:无论链路密钥是立即还是稍后完全删除,命令都会在密钥从存储中标记或删除后完成。意味着,使用
HCI_Read_Stored_Link_Key
命令将无法再读取这些密钥。
二、命令格式及参数
2.1. HCI_Delete_Stored_Link_Key
命令格式
HCI_Delete_Stored_Link_Key
命令遵循蓝牙HCI)的命令格式。
该命令由操作码(OCF)和参数部分组成。
- 操作码(OCF):对于HCI_Delete_Stored_Link_Key命令,其操作码是固定的,用于标识该命令。
- 参数部分:包含要删除的链路密钥的相关信息。
-
BD_ADDR(蓝牙设备地址):
- 48位的蓝牙设备地址,用于唯一标识一个蓝牙设备。
- 当需要删除特定设备的链路密钥时,应提供该设备的蓝牙地址。
-
Delete_All(删除所有标志):
- 1位的标志位,用于指示是否删除所有存储的链路密钥。
- 如果设置为1(或true),则表示删除所有存储的链路密钥,此时BD_ADDR参数将被忽略。
- 如果设置为0(或false),则表示仅删除与指定BD_ADDR相关的链路密钥。
-
2.2. BD_ADDR
BD_ADDR
用于指定要删除的Link Key所对应的蓝牙设备。蓝牙MAC地址-CSDN博客
- 大小:
BD_ADDR
的大小为 6 个八位组(octets),在编程中通常表示为一个长度为 6 的字节数组(例如在 C 语言中可以使用uint8_t[6]
)。 - 数据类型:无符号 8 位字节数组,用于存储蓝牙设备的地址信息。
2.3. Delete_All
Delete_All_Flag表示是否删除所有已存储的link key。
0x00
:仅删除与指定BD_ADDR
相关联的链路密钥。当此值被设置时,命令必须包含一个有效的BD_ADDR
参数,该参数指定了要删除链路密钥的蓝牙设备。0x01
:删除所有存储的链路密钥。当此值被设置时,BD_ADDR
参数将被忽略,因为命令将作用于所有存储的链路密钥。
三、生成事件及参数
3.1. HCI_Command_Complete事件
当HCI_Delete_Stored_Link_Key命令执行完成后,会生成一个HCI_Command_Complete事件。这个事件是蓝牙HCI协议中定义的一种标准事件,用于通知主机(Host)关于命令执行的结果。
-
事件代码:HCI_Command_Complete是一个特定的事件代码,用于标识该事件。
-
参数:该事件通常包含以下参数:
- Number_of_Completed_Commands:表示已完成的命令数量。对于HCI_Delete_Stored_Link_Key命令,这个值通常为1,因为每个HCI命令通常是单独执行的。
- Command_Opcode:表示已完成命令的操作码(Opcode)。
- Status:表示命令执行的状态。这是一个重要的参数,用于指示命令是否成功执行。常见的状态值包括0x00(成功)和各种错误代码。
- Return_Parameters:对于HCI_Delete_Stored_Link_Key命令,如果成功执行,可能包含被删除的链路密钥数量等信息。
3.2. Status
Status
用于指示 HCI_Delete_Stored_Link_Key
命令的执行结果。
0x00
:表示HCI_Delete_Stored_Link_Key
命令成功执行。意味着指定的链路密钥(如果提供了BD_ADDR
)或所有存储的链路密钥(如果Delete_All
设置为0x01
)已被成功删除。0x01
到0xFF
:表示HCI_Delete_Stored_Link_Key
命令执行失败。蓝牙Controller错误代码全面概览_connection rejected due to limited resources-CSDN博客
3.3. Num_Keys_Deleted
Num_Keys_Deleted
参数用于指示在执行HCI_Delete_Stored_Link_Key
命令后从存储中删除的链路密钥(Link Keys)的数量。
Num_Keys_Deleted 的大小为 2 个八位组(octets),在编程中通常使用一个无符号 16 位整数(例如在 C 语言中可以用uint16_t)来表示 。这种数据类型选择是为了能够表示一定范围内的链路密钥删除数量,2 个字节可以表示 0 到 65535 之间的无符号整数。
四、命令执行流程
4.1. 命令发送阶段
- 主机构建命令:构建包含操作码和参数(BD_ADDR或Delete_All)的HCI_Delete_Stored_Link_Key命令数据包。
- 若Delete_All=0x00,需指定BD_ADDR。
- 若Delete_All=0x01,忽略BD_ADDR。
- 发送命令:通过HCI接口将命令数据包发送给蓝牙控制器。
4.2. 控制器处理阶段
- 接收并解析命令:蓝牙控制器解析操作码和参数。
- 删除链路密钥:
- 若Delete_All=0x01,遍历并删除所有链路密钥(正在使用的先标记,待连接断开后完全删除)。
- 若Delete_All=0x00,根据BD_ADDR查找并删除对应的链路密钥(同样处理正在使用的)。
4.3. 命令完成反馈阶段
- 生成事件数据包:控制器完成处理后,生成HCI_Command_Complete事件数据包,包含事件码、状态字段、操作码和Num_Keys_Deleted字段。
- 发送反馈:将事件数据包发送回主机。
4.4. 主机处理反馈阶段
- 接收并解析反馈:主机解析事件数据包中的各个字段。
- 判断命令结果:
- 若状态为0x00,确认命令成功,并记录删除的链路密钥数量。
- 若状态不为0x00,根据错误状态码确定失败原因,进行后续处理。
4.5. 示例代码
下面提供一个简化的、高层次的伪代码示例,以展示如何在C语言中实现这一流程的主要步骤。
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>// 假设的HCI接口函数(在实际实现中,这些函数将由蓝牙协议栈提供)
bool hci_send_command(uint16_t opcode, uint8_t *parameters, uint8_t parameter_length, uint8_t *response, uint16_t *response_length);
void hci_event_callback(uint8_t *event, uint16_t event_length);// 假设的链路密钥存储和管理函数(在实际实现中,这些函数将处理实际的存储和删除操作)
bool delete_link_key(uint8_t *bd_addr, bool delete_all);
uint8_t get_num_deleted_keys(void);// HCI_Delete_Stored_Link_Key命令的OCF(操作码字段)
#define HCI_OP_DELETE_STORED_LINK_KEY 0x0012// 示例函数:发送HCI_Delete_Stored_Link_Key命令
bool send_delete_stored_link_key_command(uint8_t *bd_addr, bool delete_all) {uint8_t parameters[7]; // BD_ADDR是6个字节,加上1个字节的Delete_All标志if (!delete_all) {// 如果不是删除所有,则需要指定BD_ADDRmemcpy(parameters, bd_addr, 6);parameters[6] = 0x00; // Delete_All设置为0x00} else {// 如果是删除所有,则忽略BD_ADDR,只设置Delete_All标志// 这里我们其实不需要填充BD_ADDR,但为了保持数组大小一致,可以设置为任意值或零memset(parameters, 0, 6);parameters[6] = 0x01; // Delete_All设置为0x01}uint8_t response[256]; // 假设的响应缓冲区大小uint16_t response_length = sizeof(response);// 发送命令并等待响应(在实际实现中,这可能需要一个异步回调机制)bool success = hci_send_command(HCI_OP_DELETE_STORED_LINK_KEY, parameters, delete_all ? 1 : 7, response, &response_length);// 在这里,我们假设hci_send_command函数是同步的,并且会在命令完成后返回结果。// 在实际实现中,可能需要使用事件回调来处理异步响应。// 检查响应并处理结果(在实际实现中,这将涉及解析响应数据包)// 这里我们简化处理,只检查一个假设的“成功”状态if (success && response[0] == 0x04 && response[1] == 0x0E && response[2] == 0x00 && response[3] == 0x00) {// 假设的成功响应检查(在实际实现中,这将更加复杂)// 调用链路密钥删除函数(在实际实现中,这将由蓝牙协议栈内部处理)// 但在这里我们模拟它delete_link_key(bd_addr, delete_all);// 假设的回调函数调用(在实际实现中,这将由蓝牙协议栈提供)// 来通知上层应用程序命令已完成// hci_event_callback(...);return true;} else {// 处理错误(在实际实现中,这将涉及解析错误代码并采取适当的行动)return false;}
}// 示例函数:模拟链路密钥删除操作(在实际实现中,这将处理实际的存储删除)
bool delete_link_key(uint8_t *bd_addr, bool delete_all) {// 在这里实现实际的链路密钥删除逻辑// ...// 返回删除操作是否成功的标志return true;
}// 示例函数:获取已删除的链路密钥数量(在实际实现中,这将从某个状态或日志中检索信息)
uint8_t get_num_deleted_keys(void) {// 在这里实现获取已删除链路密钥数量的逻辑// ...// 返回已删除的链路密钥数量return 1; // 假设删除了1个(或全部,如果delete_all为true)
}int main() {uint8_t bd_addr[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; // 示例蓝牙地址// 发送删除链路密钥命令(删除指定地址的链路密钥)bool result = send_delete_stored_link_key_command(bd_addr, false);if (result) {printf("Successfully deleted link key for BD_ADDR: %02X:%02X:%02X:%02X:%02X:%02X\n",bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);} else {printf("Failed to delete link key for BD_ADDR: %02X:%02X:%02X:%02X:%02X:%02X\n",bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);}// 发送删除所有链路密钥命令result = send_delete_stored_link_key_command(NULL, true);if (result) {printf("Successfully deleted all link keys. Number of deleted keys: %d\n", get_num_deleted_keys());} else {printf("Failed to delete all link keys.\n");}return 0;
}
五、应用场景
- 设备安全维护
-
当用户不再使用某个已配对的蓝牙设备时,或设备丢失、被盗时,可通过此命令删除对应的链路密钥,防止非法连接。
-
在设备软件更新或恢复出厂设置时,删除所有链路密钥,确保设备安全重置。
-
- 取消蓝牙设备配对:用户希望取消两个蓝牙设备之间的配对关系时,可删除链路密钥,使设备需要重新配对才能建立安全连接。
- 清除旧的或不再使用的链路密钥:随着时间推移,用户可能连接多个蓝牙设备,产生多个链路密钥。定期清除旧的或不再使用的密钥,有助于保持设备安全性和管理简洁性。
- 重置蓝牙设备的安全设置:在设备被盗或丢失后,通过删除所有链路密钥,确保设备在重新配对前不会被未经授权的设备访问。
- 故障排查和修复:当蓝牙连接出现问题时,如无法建立连接或连接频繁断开,可尝试删除有问题的链路密钥,然后重新配对以解决问题。
- 多设备管理与优化:
-
在蓝牙网关或服务器设备中,删除不再使用或过期的链路密钥,释放存储空间,提高设备运行效率。
-
对于频繁更换连接设备的场景,如蓝牙测试设备,每次测试后删除链路密钥,为下次测试准备干净环境。
-
- 遵守安全策略和合规性要求:在某些行业或组织中,可能需要遵守特定的安全策略和合规性要求,定期删除不再需要的蓝牙链路密钥。
六、注意事项
6.1. 确认删除对象
- 准确性:务必确认要删除的链路密钥与对应的蓝牙设备匹配,避免错误删除导致连接中断。
- 必要性:评估删除链路密钥的必要性,仅在确实需要取消配对、优化存储或遵守安全策略时执行。
6.2. 设备状态与连接
- 设备状态:确保蓝牙设备处于可操作状态,能够接收和执行HCI命令。
- 连接状态:若设备与待删除链路密钥对应的蓝牙设备仍连接,建议先断开连接再执行删除操作。
6.3. 命令参数与执行
- 参数设置:
- BD_ADDR准确性:当Delete_All为0时,BD_ADDR必须准确无误。
- Delete_All谨慎使用:设置为1时会删除所有链路密钥,需确认必要性并通知用户可能导致的连接中断。
- 命令格式:按照HCI协议规范构造命令的OpCode和参数。
- 反馈处理:等待并正确处理HCI_Command_Complete事件,根据状态字段判断命令是否成功执行。失败时,根据错误代码表找出原因并采取相应措施。
6.4. 并发操作与状态管理
- 并发操作:避免并发发送HCI_Delete_Stored_Link_Key命令或与其他蓝牙命令冲突,可通过同步机制确保命令顺序执行。
- 链路密钥状态:正在使用的密钥在删除后不会立即完全删除,需考虑连接未断开时密钥的删除状态。
- 设备连接管理:删除链路密钥后,及时更新设备连接管理模块信息,避免连接管理混乱。
6.5. 安全与隐私
- 重新配对:删除链路密钥后,设备需重新配对才能建立安全连接,确保用户了解此流程。
- 数据保护:在删除过程中确保数据安全和隐私性,避免在不安全环境中执行操作。
6.6. 兼容性与版本
- 兼容性:确认蓝牙设备和HCI实现支持该命令,注意不同版本蓝牙协议和HCI实现的差异。
- 版本更新:设备软件或固件升级后,重新检查HCI命令的兼容性和正确性。
综上所述,HCI_Delete_Stored_Link_Key
命令是蓝牙安全管理中的一个重要工具,用于删除不再需要的链路密钥,从而维护设备的安全性和存储效率。
相关文章:

【0x0012】HCI_Delete_Stored_Link_Key命令详解
目录 一、命令参数 二、命令格式及参数 2.1. HCI_Delete_Stored_Link_Key 命令格式 2.2. BD_ADDR 2.3. Delete_All 三、生成事件及参数 3.1. HCI_Command_Complete事件 3.2. Status 3.3. Num_Keys_Deleted 四、命令执行流程 4.1. 命令发送阶段 4.2. 控制器处理阶段…...

console的各种方法
console除了常用的log方法,还有很多方便的方法。 console.table 表格 将数据以表格形式展示 console.group 分组 console.group、console.groupEnd:开启、结束分组,使结构更加清晰 console.dir 对象 打印函数或dom时,log无法打…...

spring boot关于系统首页自动跳转拼接到index
业务说明 通过http://localhost:8091访问服务器时,会动态的跳转到系统的欢迎页面. 实现原理: 说明程序启动时会自动的加载一个默认的请求路径(url:http://localhost:8091/) index 之后动态的拼接前缀和后缀. /WEB-INF/views/index.jsp...

指针生成网络(PGN)详细指南(引入)
一、Seq2Seq模型:编码-解码框架的开山之作 我们首先要了解的是seq2seq(Sequence-to-Sequence)模型。它最早由Google在2014年的一篇论文中提出,是第一个真正意义上的端到端的编码器-解码器(Encoder-Decoder)…...

案例研究丨浪潮云洲通过DataEase推进多维度数据可视化建设
浪潮云洲工业互联网有限公司(以下简称为“浪潮云洲”)成立于2018年,定位于工业数字基础设施建设商、具有国际影响力的工业互联网平台运营商、生产性互联网头部服务商。截至目前,浪潮云洲工业互联网平台连续五年入选跨行业跨领域工…...

k8s 蓝绿发布、滚动发布、灰度发布
在Kubernetes(k8s)中,蓝绿发布、滚动发布、灰度发布(金丝雀发布)是三种常见的应用部署和更新策略。下面将分别对这几种发布方式进行说明,并给出相应的例子。 蓝绿发布 蓝绿发布是一种无缝切换版本的部署策…...
UWB原理:AOA测角原理Angel of Arrival
AOA测角原理Angel of Arrival 准备工作: UWB默认使用channel=9,Frequency = 7987.2mMhz,约8GHz。 波长 天线RX1, RX2间距一般为20mm左右,假如发射端TX离2个RX距离2m=2000mm,大约是100倍天线间距。2个入射角可以近似相同。 测角原理: <...

plus.runtime.install在android10无效
在 Android 10 中,使用 plus.runtime.install 方法来进行动态安装应用或进行其他操作可能会失效。这是因为从 Android 10 开始,操作系统在安全性和隐私方面做了很多改进,特别是与应用安装相关的权限变更。 在 Android 10(API 级别…...

7.C++中的函数
C中的函数 在 C 中,函数是一个重要的概念,它是将一段相对独立的、完成特定任务的代码封装起来的程序模块。以下是关于 C 中函数的详细介绍: 函数的定义 函数定义由函数头和函数体组成,其一般形式如下: 返回值类型 …...

上位机知识篇---Python数据图表可视化
文章目录 前言第一部分:Matplotlib1. 图形和轴(Figure and Axes)FigureAxes创建一个新的图形在图形中添加一个或多个轴 2. 绘图命令绘制折线图绘制散点图绘制条形图绘制饼图绘制直方图等高线图(Contour plot)ÿ…...

详解:TCP/IP五层(四层)协议模型
一.五层(四层)模型 1.概念 TCP/IP协议模型分为五层:物理层、数据链路层、网络层、传输层和应用层。这五层每一层都依赖于其下一层给它提供的网络去实现需求。 1)物理层:这是最基本的一层,也是最接近硬件…...

【原生记忆能力 怎么让大模型拥有原生的记忆能力】
首先,需要明确“原生记忆能力”具体指的是什么。通常来说,大模型如GPT-3或GPT-4在生成回复时是基于训练数据的模式识别,而不是真正的记忆。所以用户可能希望模型能够持续记住之前的交互信息,或者在多次使用中积累知识,…...

百度APP iOS端磁盘优化实践(上)
01 概览 在APP的开发中,磁盘管理已成为不可忽视的部分。随着功能的复杂化和数据量的快速增长,如何高效管理磁盘空间直接关系到用户体验和APP性能。本文将结合磁盘管理的实践经验,详细介绍iOS沙盒环境下的文件存储规范,探讨业务缓…...

qml Dialog详解
1、概述 Dialog是QML(Qt Modeling Language)中用于显示对话框的组件,它提供了一个模态窗口,通常用于与用户进行重要交互,如确认操作、输入信息或显示警告等。Dialog组件具有灵活的布局和样式选项,可以轻松…...

2025年的校招管理系统会全面实现智能化吗?
随着科技的不断进步,企业的招聘方式也在不断地演变。特别是在校园招聘领域,传统的招聘方法已经难以满足现代企业的需求。2025年的校招管理系统是否会全面实现智能化?这是一个值得探讨的话题。 想象一下,每年的校招季,…...

【Unity】使用Canvas Group改变UI的透明度
目录 一、前言二、Canvas Group三、结合DOTween达到画面淡进的效果 一、前言 在平时开发中,可以通过控制材质、Color改变UI透明度,除此之外还可以CanvasGroup组件来控制透明度。 二、Canvas Group 官方文档链接👉👉 点击进入 …...

2024年博客之星主题创作|2024年度感想与新技术Redis学习
Redis工具深入了解 1.引言与感想2.Redis工具了解2.分布式系统了解2.1单机架构2.2分布式是什么2.3应用服务和数据库服务分离2.4引入更多的应用服务器2.5理解负载均衡器2.6数据库读写分离2.7引入缓存2.8数据库分库分表2.9引入微服务2.10分布式系统小结 1.引言与感想 2024学习了很…...

6. 马科维茨资产组合模型+政策意图AI金融智能体(DeepSeek-V3)增强方案(理论+Python实战)
目录 0. 承前1. 幻方量化 & DeepSeek1.1 What is 幻方量化1.2 What is DeepSeek 2. 重写AI金融智能体函数3. 汇总代码4. 反思4.1 不足之处4.2 提升思路 5. 启后 0. 承前 本篇博文是对上一篇文章,链接: 5. 马科维茨资产组合模型政策意图AI金融智能体(Qwen-Max)增…...

Unity自学之旅05
Unity自学之旅05 Unity学习之旅⑤📝 AI基础与敌人行为🥊 AI导航理论知识(基础)开始实践 🎃 敌人游戏机制追踪玩家攻击玩家子弹碰撞完善游戏失败条件 🤗 总结归纳 Unity学习之旅⑤ 📝 AI基础与敌…...

linux中关闭服务的开机自启动
引言 systemctl 是 Linux 系统中用于管理 systemd 服务的命令行工具。它可以用来启动、停止、重启服务,管理服务的开机自启动,以及查看服务的状态等。 什么是 systemd? systemd 是现代 Linux 发行版中默认的 初始化系统(init sys…...

Python----Python高级(文件操作open,os模块对于文件操作,shutil模块 )
一、文件处理 1.1、文件操作的重要性和应用场景 1.1.1、重要性 数据持久化: 文件是存储数据的一种非常基本且重要的方式。通过文件,我们可 以将程序运行时产生的数据永久保存下来,以便将来使用。 跨平台兼容性: 文件是一种通用…...

ubuntu黑屏问题解决
重启Ubuntu后,系统自动进入tty1,无法进入桌面。想到前几天安装了一些主题之类的,然后今天才重启,可能是这些主题造成冲突或者问题了把。 这里直接重新安装ubuntu-desktop解决: 更新源: sudo apt-get upd…...

Java如何实现反转义
Java如何实现反转义 前提 最近做的一个需求,是热搜词增加换一批的功能。功能做完自测后,交给了测试伙伴,但是测试第二天后就提了一个bug,出现了未知词 levis。第一眼看着像公司售卖的一个品牌-李维斯。然后再扒前人写的代码&…...

动态规划(路径问题)
62. 不同路径 62. 不同路径 - 力扣(LeetCode) 动态规划思想第一步:描述状态~ dp[i][j]:表示走到i,j位置时,一共有多少种方法~ 动态规划思想第二步:状态转移方程~ 动态规划思想第三步…...

python http调用视觉模型moondream
目录 一、什么是moondream 二、资源地址 三、封装了http进行接口请求 四、代码解析 解释 可能的改进 一、什么是moondream Moondream 是一个针对视觉生成任务的深度学习模型,专注于图像理解和生成,包括图像标注(captioning)、问题回答(Visual Question Answering,…...

Spark Streaming编程基础
文章目录 1. 流式词频统计1.1 Spark Streaming编程步骤1.2 流式词频统计项目1.2.1 创建项目1.2.2 添加项目依赖1.2.3 修改源目录1.2.4 添加scala-sdk库1.2.5 创建日志属性文件 1.3 创建词频统计对象1.4 利用nc发送数据1.5 启动应用,查看结果 2. 编程模型的基本概念3…...

深入 Flutter 和 Compose 的 PlatformView 实现对比,它们是如何接入平台控件
在上一篇《深入 Flutter 和 Compose 在 UI 渲染刷新时 Diff 实现对比》发布之后,收到了大佬的“催稿”,想了解下 Flutter 和 Compose 在 PlatformView 实现上的对比,恰好过去写过不少 Flutter 上对于 PlatformView 的实现,这次恰好…...

C# OpenCV机器视觉:红外体温检测
在一个骄阳似火的夏日,全球却被一场突如其来的疫情阴霾笼罩。阿强所在的小镇,平日里熙熙攘攘的街道变得冷冷清清,人们戴着口罩,行色匆匆,眼神中满是对病毒的恐惧。阿强作为镇上小有名气的科技达人,看着这一…...

FCA-FineDataLink认证
FCA-FineDataLink证书 Part.1:判断题 (总分:18分 得分:16) 第1题 判断题 数据同步只支持写入到已存在表,不支持自动建表(得分:2分 满分:2分) 正确答案:B 你的答案&…...

第19篇:python高级编程进阶:使用Flask进行Web开发
第19篇:python高级编程进阶:使用Flask进行Web开发 内容简介 在第18篇文章中,我们介绍了Web开发的基础知识,并使用Flask框架构建了一个简单的Web应用。本篇文章将深入探讨Flask的高级功能,涵盖模板引擎(Ji…...