当前位置: 首页 > news >正文

【ESP32】ESP-IDF开发 | WiFi开发 | HTTPS服务器 + 搭建例程

1. 简介

1.1 HTTPS

        HTTPS(HyperText Transfer Protocol over Secure Socket Layer),全称安全套接字层超文本传输协议,一般理解为HTTP+SSL/TLS,通过SSL证书来验证服务器的身份,并为浏览器和服务器之间的通信进行加密。该协议使用443端口进行通信。

        它解决的是HTTP协议明文传输的不安全性,HTTPS协议在数据进行传输之前,对数据进行加密,然后再发送到服务器。这样,就算数据被第三者所截获,但是由于数据是加密的,所以你的个人信息仍然是安全的。

1.2 SSL/TLS

        SSL(Secure Socket Layer,安全套接字层):1994年为 Netscape 所研发,SSL 协议位于 TCP/IP 协议与各种应用层协议之间,为数据通讯提供安全支持。

        TLS(Transport Layer Security,传输层安全):其前身是 SSL,它最初的几个版本(SSL 1.0、SSL 2.0、SSL 3.0)由网景公司开发,1999年从 3.1 开始被 IETF 标准化并改名,发展至今已经有 TLS 1.0、TLS 1.1、TLS 1.2 三个版本。SSL 3.0和TLS 1.0由于存在安全漏洞,已经很少被使用到。

1.3 通信流程

2. 例程

        因为HTTPS相对于HTTP只是多了加密的过程,所以例程大体是沿用前一篇文章的代码,所以下面只会讲解加密部分的代码。

2.1 函数API

2.1.1 启动服务器

esp_err_t httpd_ssl_start(httpd_handle_t *handle, httpd_ssl_config_t *config)
  • handle:HTTPS句柄;
  • config:服务器配置。
struct httpd_ssl_config {httpd_config_t httpd;const uint8_t *servercert;size_t servercert_len;const uint8_t *cacert_pem;size_t cacert_len;const uint8_t *prvtkey_pem;size_t prvtkey_len;bool use_ecdsa_peripheral;uint8_t ecdsa_key_efuse_blk;httpd_ssl_transport_mode_t transport_mode;uint16_t port_secure;uint16_t port_insecure;bool session_tickets;bool use_secure_element;esp_https_server_user_cb *user_cb;void *ssl_userdata;esp_tls_handshake_callback cert_select_cb;const char** alpn_protos;
};

        配置结构体的内容比较多,ESP-IDF也提供了HTTPD_SSL_CONFIG_DEFAULT宏进行快速默认配置,所以下面只解释一些常用的配置:

  • servercert:服务器证书;
  • servercert_len:服务器证书长度;
  • cacert_pem:CA证书;
  • cacert_len:CA证书长度;
  • prvtkey_pem:私钥;
  • prvtkey_len:私钥长度;
  • port_secure:安全端口,即采用https访问时的端口,默认为443;
  • port_insecure:非安全端口,即采用http访问时的端口,默认为80;
  • user_cb:用户回调,主要用于客户端连接或断开时进行自定义处理;

2.2 代码

#include "freertos/FreeRTOS.h"#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "sys/socket.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "netdb.h"
#include "arpa/inet.h"
#include "esp_https_server.h"
#include "esp_tls.h"
#include "mbedtls/base64.h"#include <string.h>#define TAG "app"static httpd_handle_t server_handle;static const uint8_t servercert[] = 
"-----BEGIN CERTIFICATE-----\n\
MIIDKzCCAhOgAwIBAgIUBxM3WJf2bP12kAfqhmhhjZWv0ukwDQYJKoZIhvcNAQEL\n\
BQAwJTEjMCEGA1UEAwwaRVNQMzIgSFRUUFMgc2VydmVyIGV4YW1wbGUwHhcNMTgx\n\
MDE3MTEzMjU3WhcNMjgxMDE0MTEzMjU3WjAlMSMwIQYDVQQDDBpFU1AzMiBIVFRQ\n\
UyBzZXJ2ZXIgZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n\
ALBint6nP77RCQcmKgwPtTsGK0uClxg+LwKJ3WXuye3oqnnjqJCwMEneXzGdG09T\n\
sA0SyNPwrEgebLCH80an3gWU4pHDdqGHfJQa2jBL290e/5L5MB+6PTs2NKcojK/k\n\
qcZkn58MWXhDW1NpAnJtjVniK2Ksvr/YIYSbyD+JiEs0MGxEx+kOl9d7hRHJaIzd\n\
GF/vO2pl295v1qXekAlkgNMtYIVAjUy9CMpqaQBCQRL+BmPSJRkXBsYk8GPnieS4\n\
sUsp53DsNvCCtWDT6fd9D1v+BB6nDk/FCPKhtjYOwOAZlX4wWNSZpRNr5dfrxKsb\n\
jAn4PCuR2akdF4G8WLUeDWECAwEAAaNTMFEwHQYDVR0OBBYEFMnmdJKOEepXrHI/\n\
ivM6mVqJgAX8MB8GA1UdIwQYMBaAFMnmdJKOEepXrHI/ivM6mVqJgAX8MA8GA1Ud\n\
EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADiXIGEkSsN0SLSfCF1VNWO3\n\
emBurfOcDq4EGEaxRKAU0814VEmU87btIDx80+z5Dbf+GGHCPrY7odIkxGNn0DJY\n\
W1WcF+DOcbiWoUN6DTkAML0SMnp8aGj9ffx3x+qoggT+vGdWVVA4pgwqZT7Ybntx\n\
bkzcNFW0sqmCv4IN1t4w6L0A87ZwsNwVpre/j6uyBw7s8YoJHDLRFT6g7qgn0tcN\n\
ZufhNISvgWCVJQy/SZjNBHSpnIdCUSJAeTY2mkM4sGxY0Widk8LnjydxZUSxC3Nl\n\
hb6pnMh3jRq4h0+5CZielA4/a+TdrNPv/qok67ot/XJdY3qHCCd8O2b14OVq9jo=\n\
-----END CERTIFICATE-----";static const uint8_t prvkey[] = 
"-----BEGIN PRIVATE KEY-----\n\
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCwYp7epz++0QkH\n\
JioMD7U7BitLgpcYPi8Cid1l7snt6Kp546iQsDBJ3l8xnRtPU7ANEsjT8KxIHmyw\n\
h/NGp94FlOKRw3ahh3yUGtowS9vdHv+S+TAfuj07NjSnKIyv5KnGZJ+fDFl4Q1tT\n\
aQJybY1Z4itirL6/2CGEm8g/iYhLNDBsRMfpDpfXe4URyWiM3Rhf7ztqZdveb9al\n\
3pAJZIDTLWCFQI1MvQjKamkAQkES/gZj0iUZFwbGJPBj54nkuLFLKedw7DbwgrVg\n\
0+n3fQ9b/gQepw5PxQjyobY2DsDgGZV+MFjUmaUTa+XX68SrG4wJ+DwrkdmpHReB\n\
vFi1Hg1hAgMBAAECggEAaTCnZkl/7qBjLexIryC/CBBJyaJ70W1kQ7NMYfniWwui\n\
f0aRxJgOdD81rjTvkINsPp+xPRQO6oOadjzdjImYEuQTqrJTEUnntbu924eh+2D9\n\
Mf2CAanj0mglRnscS9mmljZ0KzoGMX6Z/EhnuS40WiJTlWlH6MlQU/FDnwC6U34y\n\
JKy6/jGryfsx+kGU/NRvKSru6JYJWt5v7sOrymHWD62IT59h3blOiP8GMtYKeQlX\n\
49om9Mo1VTIFASY3lrxmexbY+6FG8YO+tfIe0tTAiGrkb9Pz6tYbaj9FjEWOv4Vc\n\
+3VMBUVdGJjgqvE8fx+/+mHo4Rg69BUPfPSrpEg7sQKBgQDlL85G04VZgrNZgOx6\n\
pTlCCl/NkfNb1OYa0BELqWINoWaWQHnm6lX8YjrUjwRpBF5s7mFhguFjUjp/NW6D\n\
0EEg5BmO0ePJ3dLKSeOA7gMo7y7kAcD/YGToqAaGljkBI+IAWK5Su5yldrECTQKG\n\
YnMKyQ1MWUfCYEwHtPvFvE5aPwKBgQDFBWXekpxHIvt/B41Cl/TftAzE7/f58JjV\n\
MFo/JCh9TDcH6N5TMTRS1/iQrv5M6kJSSrHnq8pqDXOwfHLwxetpk9tr937VRzoL\n\
CuG1Ar7c1AO6ujNnAEmUVC2DppL/ck5mRPWK/kgLwZSaNcZf8sydRgphsW1ogJin\n\
7g0nGbFwXwKBgQCPoZY07Pr1TeP4g8OwWTu5F6dSvdU2CAbtZthH5q98u1n/cAj1\n\
noak1Srpa3foGMTUn9CHu+5kwHPIpUPNeAZZBpq91uxa5pnkDMp3UrLIRJ2uZyr8\n\
4PxcknEEh8DR5hsM/IbDcrCJQglM19ZtQeW3LKkY4BsIxjDf45ymH407IQKBgE/g\n\
Ul6cPfOxQRlNLH4VMVgInSyyxWx1mODFy7DRrgCuh5kTVh+QUVBM8x9lcwAn8V9/\n\
nQT55wR8E603pznqY/jX0xvAqZE6YVPcw4kpZcwNwL1RhEl8GliikBlRzUL3SsW3\n\
q30AfqEViHPE3XpE66PPo6Hb1ymJCVr77iUuC3wtAoGBAIBrOGunv1qZMfqmwAY2\n\
lxlzRgxgSiaev0lTNxDzZkmU/u3dgdTwJ5DDANqPwJc6b8SGYTp9rQ0mbgVHnhIB\n\
jcJQBQkTfq6Z0H6OoTVi7dPs3ibQJFrtkoyvYAbyk36quBmNRjVh6rc8468bhXYr\n\
v/t+MeGJP/0Zw8v/X2CFll96\n\
-----END PRIVATE KEY-----";static const char index_html[] = " \
<!DOCTYPE html> \
<html> \
<head> \
<meta charset=\"utf-8\"> \
<title>index</title> \
</head> \
\
<body> \<h1>Hello from ESP32</h1> \
</body> \<form action=\"/hello\" method=\"post\"> \<label for=\"name\">What's your name:</label> \<input type=\"text\" id=\"name\" name=\"name\" required> \<input type=\"submit\" value=\"OK\"></button> \</form> \
</html> \
";static const char hello_html_template[] = " \
<!DOCTYPE html> \
<html> \
<head> \
<meta charset=\"utf-8\"> \
<title>hello</title> \
</head> \
\
<body> \<h1>Oh, Hello %s</h1> \
</body> \
\
</html> \
";static esp_err_t index_get_handler(httpd_req_t *req)
{/* 获取Host信息 */size_t buf_len = httpd_req_get_hdr_value_len(req, "Host") + 1;if (buf_len > 1) {char *buf = malloc(buf_len);if (httpd_req_get_hdr_value_str(req, "Host", buf, buf_len) == ESP_OK) {ESP_LOGI(TAG, "Get request to host: %s", buf);}free(buf);}/* 回复数据包 */httpd_resp_sendstr(req, index_html);return ESP_OK;
}static const httpd_uri_t index_uri = {.uri       = "/index",.method    = HTTP_GET,.handler   = index_get_handler,.user_ctx  = NULL
};static esp_err_t hello_post_handler(httpd_req_t *req)
{/* 获取Host信息 */size_t buf_len = httpd_req_get_hdr_value_len(req, "Host") + 1;if (buf_len > 1) {char *buf = malloc(buf_len);if (httpd_req_get_hdr_value_str(req, "Host", buf, buf_len) == ESP_OK) {ESP_LOGI(TAG, "Post request to host: %s", buf);}free(buf);}/* 获取内容长度 */int len = 0;{char *buf = malloc(128);memset(buf, 0, 128);if (httpd_req_get_hdr_value_str(req, "Content-Length", buf, 128) != ESP_OK) {ESP_LOGE(TAG, "Get content length failed");return ESP_FAIL;}len = atoi(buf) + 1;free(buf);}/* 获取表单数据 */char *buf = malloc(len);memset(buf, 0, len);if (httpd_req_recv(req, buf, len) <= 0) {ESP_LOGE(TAG, "Receive request content failed");return ESP_FAIL;}if (strstr(buf, "name=") == NULL) {ESP_LOGE(TAG, "Can't found fleid \"name\"");free(buf);return ESP_FAIL;}/* 发送数据 */char *hello_html = malloc(1024);snprintf(hello_html, 1024, hello_html_template, buf + strlen("name="));httpd_resp_sendstr(req, hello_html);free(buf);free(hello_html);return ESP_OK;
}static const httpd_uri_t hello_uri = {.uri       = "/hello",.method    = HTTP_POST,.handler   = hello_post_handler,.user_ctx  = NULL
};static void print_peer_cert_info(const mbedtls_ssl_context *ssl)
{const mbedtls_x509_crt *cert;const size_t buf_size = 1024;char *buf = calloc(buf_size, sizeof(char));if (buf == NULL) {ESP_LOGE(TAG, "Out of memory - Callback execution failed!");return;}cert = mbedtls_ssl_get_peer_cert(ssl);if (cert != NULL) {mbedtls_x509_crt_info((char *) buf, buf_size - 1, "    ", cert);ESP_LOGI(TAG, "Peer certificate info:\n%s", buf);} else {ESP_LOGW(TAG, "Could not obtain the peer certificate!");}free(buf);
}static void https_server_user_callback(esp_https_server_user_cb_arg_t *user_cb)
{mbedtls_ssl_context *ssl_ctx = NULL;switch(user_cb->user_cb_state) {case HTTPD_SSL_USER_CB_SESS_CREATE:int sockfd = -1;esp_err_t esp_ret;esp_ret = esp_tls_get_conn_sockfd(user_cb->tls, &sockfd);if (esp_ret != ESP_OK) {ESP_LOGE(TAG, "Error in obtaining the sockfd from tls context");break;}ESP_LOGI(TAG, "Socket FD: %d", sockfd);ssl_ctx = (mbedtls_ssl_context *) esp_tls_get_ssl_context(user_cb->tls);if (ssl_ctx == NULL) {ESP_LOGE(TAG, "Error in obtaining ssl context");break;}ESP_LOGI(TAG, "Current Ciphersuite: %s", mbedtls_ssl_get_ciphersuite(ssl_ctx));break;case HTTPD_SSL_USER_CB_SESS_CLOSE:ssl_ctx = (mbedtls_ssl_context *) esp_tls_get_ssl_context(user_cb->tls);if (ssl_ctx == NULL) {ESP_LOGE(TAG, "Error in obtaining ssl context");break;}print_peer_cert_info(ssl_ctx);break;default:break;}
}static void event_handler(void* arg,esp_event_base_t event_base,int32_t event_id,void* event_data)
{if (event_base == IP_EVENT) {if (event_id == IP_EVENT_STA_GOT_IP) {/* 配置 */httpd_ssl_config_t conf = HTTPD_SSL_CONFIG_DEFAULT();conf.servercert = servercert;conf.servercert_len = sizeof(servercert);conf.prvtkey_pem = prvkey;conf.prvtkey_len = sizeof(prvkey);conf.user_cb = https_server_user_callback;/* 启动服务器 */esp_err_t ret = httpd_ssl_start(&server_handle, &conf);if (ESP_OK != ret) {ESP_LOGI(TAG, "Error starting server!");return;}/* 注册URI */httpd_register_uri_handler(server_handle, &index_uri);httpd_register_uri_handler(server_handle, &hello_uri);ip_event_got_ip_t *data = event_data;ESP_LOGI(TAG, "HTTPS server started at https://" IPSTR "/index", IP2STR(&(data->ip_info.ip)));}} else if (event_base == WIFI_EVENT) {if (event_id == WIFI_EVENT_STA_DISCONNECTED) {static uint32_t retry = 1;ESP_LOGW(TAG, "Try reconnect WiFi, retry %lu", retry);vTaskDelay(500 / portTICK_PERIOD_MS);esp_wifi_connect();retry++;} else if (event_id == WIFI_EVENT_STA_START) {esp_wifi_connect();}}
}int app_main()
{/* 初始化NVS */esp_err_t ret = nvs_flash_init();if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {ESP_ERROR_CHECK(nvs_flash_erase());ESP_ERROR_CHECK(nvs_flash_init());}/* 初始化WiFi协议栈 */ESP_ERROR_CHECK(esp_netif_init());ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_create_default_wifi_sta();wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg));ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&event_handler,NULL,NULL));ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,IP_EVENT_STA_GOT_IP,&event_handler,NULL,NULL));wifi_config_t wifi_config = {.sta = {.ssid = "Your SSID",.password = "Your Password",.threshold.authmode = WIFI_AUTH_WPA_WPA2_PSK,},};ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));ESP_ERROR_CHECK(esp_wifi_start());return 0;
}

        https服务器需要配置自己的公钥和私钥,我这里使用的是官方例程给的,当然也可以自己生成;例程中也注册了用户回调,来演示如何获取客户端的套接字描述符和查看客户端的SSL验证信息。

        调用httpd_ssl_start函数即可启动服务器,服务器启动后调用httpd_register_uri_handler函数注册URI服务,这里后面就跟上一篇文章的一样了。

        网页的内容就跟之前的一样,在输入框中填写自己的名字,点击“OK”按钮就会跳转到另一个页面。

 

例程的log有时候会弹出0x7780错误,一般是由于没有设置CA证书导致,客户端或服务器认为对方不安全。 

相关文章:

【ESP32】ESP-IDF开发 | WiFi开发 | HTTPS服务器 + 搭建例程

1. 简介 1.1 HTTPS HTTPS&#xff08;HyperText Transfer Protocol over Secure Socket Layer&#xff09;&#xff0c;全称安全套接字层超文本传输协议&#xff0c;一般理解为HTTPSSL/TLS&#xff0c;通过SSL证书来验证服务器的身份&#xff0c;并为浏览器和服务器之间的通信…...

Vue2 中使用 UniApp 时,生命周期钩子函数总结

在 Vue2 中使用 UniApp 时&#xff0c;生命周期钩子函数是一个重要的概念。它允许开发者在特定的时间点运行代码&#xff0c;管理组件的生命周期。以下是 Vue2 中 UniApp 常用的生命周期钩子函数总结&#xff1a; 1. beforeCreate 说明: 组件实例刚被创建&#xff0c;此时数据…...

如何在 Vue 3 中使用 Vue Router 和 Vuex

在 Vue 3 中使用 Vue Router 1. 安装 Vue Router 在项目根目录下&#xff0c;通过 npm 或 yarn 安装 Vue Router 4&#xff08;适用于 Vue 3&#xff09;&#xff1a; npm install vue-router4 # 或者使用 yarn yarn add vue-router42. 创建路由配置文件 在 src 目录下创建…...

Fiori APP配置中的Semantic object 小bug

在配置自开发程序的Fiori Tile时&#xff0c;需要填入Semantic Object。正常来说&#xff0c;是需要通过事务代码/N/UI2/SEMOBJ来提前新建的。 但是在S4 2022中&#xff0c;似乎存在一个bug&#xff0c;即无需新建也能输入自定义的Semantic Object。 如下&#xff0c;当我们任…...

【触想智能】工业显示器和普通显示器的区别以及工业显示器的主要应用领域分析

在现代工业中&#xff0c;工业显示器被广泛应用于各种场景&#xff0c;从监控系统到生产控制&#xff0c;它们在实时数据显示、操作界面和信息传递方面发挥着重要作用。与普通显示器相比&#xff0c;工业显示器在耐用性、可靠性和适应特殊环境的能力上有着显著的差异。 触想工业…...

BPMN.js 与 DeepSeek 集成:打造个性化 Web 培训项目的秘诀

在数字化时代&#xff0c;Web培训项目的需求日益增长&#xff0c;特别是对于程序员群体&#xff0c;他们寻求高效、灵活的方式来提升自己的技能。本文将深入探讨如何评估BPMN.js与DeepSeek集成方案&#xff0c;以满足开发Web培训项目的需求。 BPMN.js 的优势 BPMN.js是一个专…...

第二月:学习 NumPy、Pandas 和 Matplotlib 是数据分析和科学计算的基础

以下是一个为期 **1 个月&#xff08;30 天&#xff09;**的详细学习计划&#xff0c;精确到每天的学习内容和练习作业&#xff0c;帮助你系统地掌握 NumPy、Pandas 和 Matplotlib 的核心功能。 第 1 周&#xff1a;NumPy 基础 Day 1&#xff1a;NumPy 简介与数组创建 学习内…...

安全测试|SSRF请求伪造

前言 SSRF漏洞是一种在未能获取服务器权限时&#xff0c;利用服务器漏洞&#xff0c;由攻击者构造请求&#xff0c;服务器端发起请求的安全漏洞&#xff0c;攻击者可以利用该漏洞诱使服务器端应用程序向攻击者选择的任意域发出HTTP请求。 很多Web应用都提供了从其他的服务器上…...

Flink提交pyflink任务

1.官方文档&#xff1a; flink1.14:https://nightlies.apache.org/flink/flink-docs-release-1.14/docs/deployment/cli/#submitting-pyflink-jobs flink1.18:https://nightlies.apache.org/flink/flink-docs-release-1.18/docs/deployment/cli/#submitting-pyflink-jobs 2.提…...

对称算法模式之CTR

Note 计数器模式&#xff0c;通过加密递增计数器生成密钥流&#xff0c;后密钥流与明文分组异或得密文分组可并行性进行加密或者解密&#xff0c;性能较高明文可以是任意长度&#xff0c;不需要填充可以直接加密或解密指定块&#xff0c;块与块间不具有依赖关系 参数说明 任…...

Map 和 Set

目录 一、搜索 概念&#xff1a; 模型&#xff1a; 二、Map ​编辑 1.Map 实例化&#xff1a; 2. Map的常见方法&#xff1a; 3.Map的常见方法演示&#xff1a; 1. put(K key, V value)&#xff1a;添加键值对 3. containsKey(Object key)&#xff1a;检查键是否存在 4.…...

STOMP协议

引用&#xff1a;https://blog.csdn.net/print_helloword/article/details/142597122 什么是STOMP协议 STOMP (simple text oriented messaging protocol): 一种简单的&#xff0c;基于文本的消息传输协议&#xff0c;&#xff0c;&#xff0c;最初是为了解决在消息队列中&am…...

手动埋点的demo

上代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>埋点示例</title> </head><b…...

大模型开发实战篇5:多模态--文生图模型API

大模型文生图是一种基于人工智能大模型的技术&#xff0c;能够将自然语言文本描述转化为对应的图像。目前非常火的AI大模型赛道&#xff0c;有很多公司在此赛道竞争。详情可看这篇文章。 今天我们来看下如何调用WebAPI来实现文生图功能。我们一般都会将OpenAI的接口&#xff0…...

【大模型】DeepSeek 高级提示词技巧使用详解

目录 一、前言 二、DeepSeek 通用提示词技巧 2.1 DeepSeek 通用提示词技巧总结 三、DeepSeek 进阶使用技巧 3.1 DeepSeek一个特定角色的人设 3.1.1 为DeepSeek设置角色操作案例一 3.1.2 为DeepSeek设置角色操作案例二 3.2 DeepSeek开放人设升级 3.2.1 特殊的人设&#…...

【第14章:神经符号集成与可解释AI—14.2 可解释AI技术:LIME、SHAP等的实现与应用案例】

在这里插入图片描述 凌晨三点的ICU病房,值班医生李主任盯着AI辅助诊断系统的红色警报——这套准确率高达95%的深度学习系统,突然建议对一位肾衰竭患者进行肝移植手术。正当医疗组陷入混乱时,李主任打开了系统的"解释模式",屏幕上立即跳出SHAP分析图:模型误将CT…...

Python中使用Minio实现图像或视频文件的存储

目录 一、Minio的基本介绍1.Minio是什么2.Minio的优势 二、使用步骤1.启动Minio2.创建桶3.在Python中使用Minio3.1安装并导入minio包3.2创建mino_utils工具类 三、操作演示1.引入minio_utils工具类2.上传视频文件3.获取视频文件 总结 一、Minio的基本介绍 1.Minio是什么 Mini…...

Kubernetes-master 组件

以下是Kubernetes Master Machine的组件。 etcd 它存储集群中每个节点可以使用的配置信息。它是一个高可用性键值存储&#xff0c;可以在多个节点之间分布。只有Kubernetes API服务器可以访问它&#xff0c;因为它可能具有一些敏感信息。这是一个分布式键值存储&#xff0c;所…...

人形机器人 - 仿生机器人核心技术与大小脑

以下是针对仿生机器人核心技术的结构化总结,涵盖通用核心技术与**“大脑-小脑”专用架构**两大方向: 一、机器人通用核心技术 这些技术是仿生机器人实现功能的基础,与生物体的“身体能力”对应: 1. 感知与交互技术 多模态传感器融合 视觉:3D视觉(如RGB-D相机)、动态目…...

OpenAI 快速入门

文章来源&#xff1a;OpenAI开发者平台 | OpenAI开发文档|OpenAI中文官方文档|ChatGPT中文版|ChatGPT教程 开发人员快速入门 了解如何发出您的第一个 API 请求。 OpenAI API 为最先进的 AI 模型提供了一个简单的接口&#xff0c;用于自然语言处理、图像生成、语义搜索和语音识…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

【UE5 C++】通过文件对话框获取选择文件的路径

目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 &#xff0c;这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器&#xff0c;右键点击 .uproject 文件&#xff0c;选择 "Generate Visual Studio project files"&#xff0c;重…...

Python训练营-Day26-函数专题1:函数定义与参数

题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一个名为 calculate_circle_area 的函数&#xff0c;该函数接收圆的半径 radius 作为参数&#xff0c;并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求&#xff1a;函数接收一个位置参数 radi…...