在程序中编写代码完成了WIFI模块的初始化,HTTPS请求,HTTPS获取的HTML文件解析
下面是HTTPS请求的代码
static void https_client_test(void)
{
int ret, len;
mbedtls_net_context server_fd;
unsigned int flags;
unsigned char buf[2048]; // HTML响应可能较长
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_x509_crt ca_cert;
mbedtls_debug_set_threshold(1);
mbedtls_net_init(&server_fd);
mbedtls_ssl_init(&ssl);
mbedtls_ssl_config_init(&conf);
mbedtls_x509_crt_init(&ca_cert);
// ====== 加载证书 ======
ret = mbedtls_x509_crt_parse(&ca_cert,
(const unsigned char *)timeis_ca_crt,
strlen(timeis_ca_crt) + 1);
if (ret < 0) {
printf("Failed to parse CA cert -0x%x\r\n", -ret);
goto exit;
}
// ====== 建立 TCP 连接 ======
printf("Connecting to %s:%s...\r\n", SERVER_NAME, SERVER_PORT);
if ((ret = mbedtls_net_connect(&server_fd, SERVER_NAME, SERVER_PORT,
MBEDTLS_NET_PROTO_TCP)) != 0) {
printf("TCP connect failed %d\r\n", ret);
goto exit;
}
// ====== 配置 SSL ======
if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
printf("ssl_config_defaults failed %d\r\n", ret);
goto exit;
}
mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
mbedtls_ssl_conf_rng(&conf, my_random, NULL);
mbedtls_ssl_conf_dbg(&conf, my_debug, NULL);
mbedtls_ssl_conf_ca_chain(&conf, &ca_cert, NULL);
mbedtls_ssl_conf_verify(&conf, my_verify, NULL);
//启用服务器要求的曲线
{
const mbedtls_ecp_group_id curve_list[] = {
MBEDTLS_ECP_DP_SECP256R1,
MBEDTLS_ECP_DP_SECP384R1,
MBEDTLS_ECP_DP_NONE
};
mbedtls_ssl_conf_curves(&conf, curve_list);
printf("Configured curve list: SECP256R1, SECP384R1\n");
}
if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
printf("ssl_setup failed %d\r\n", ret);
goto exit;
}
if ((ret = mbedtls_ssl_set_hostname(&ssl, SERVER_NAME)) != 0) {
printf("set_hostname failed %d\r\n", ret);
goto exit;
}
mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
// ====== TLS 握手 ======
printf("TLS handshake...\r\n");
while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
printf("Handshake failed -0x%x\r\n", -ret);
goto exit;
}
}
printf("Handshake success!\r\n");
// ====== 发送 HTTP 请求 ======
len = snprintf((char *)buf, sizeof(buf),
"GET / HTTP/1.1\r\n"
"Host: %s\r\n"
"User-Agent: GD32HTTPSClient\r\n"
"Connection: close\r\n"
"\r\n",
SERVER_NAME);
ret = mbedtls_ssl_write(&ssl, buf, len);
if (ret <= 0) {
printf("SSL write failed %d\r\n", ret);
goto exit;
}
// ====== 读取响应并提取时间 ======
printf("Reading response...\r\n");
memset(buf, 0, sizeof(buf));
size_t total_len = 0;
do {
ret = mbedtls_ssl_read(&ssl, buf + total_len, sizeof(buf) - total_len - 1);
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)
continue;
if (ret <= 0)
break;
total_len += ret;
} while (total_len < sizeof(buf) - 1);
buf[total_len] = '\0';
printf("Received %u bytes.\r\n", (unsigned)total_len);
struct tm parsed;
if (parse_time_from_title((char *)buf, &parsed) == 0) {
printf("Parsed time from <title>: %04d-%02d-%02d %02d:%02d:%02d\r\n",
parsed.tm_year + 1900, parsed.tm_mon + 1, parsed.tm_mday,
parsed.tm_hour, parsed.tm_min, parsed.tm_sec);
} else {
printf("Could not parse time from HTML <title>.\r\n");
}
mbedtls_ssl_close_notify(&ssl);
exit:
if (ret < 0) {
char errbuf[128];
mbedtls_strerror(ret, errbuf, sizeof(errbuf));
printf("Error: %s\r\n", errbuf);
}
mbedtls_net_free(&server_fd);
mbedtls_x509_crt_free(&ca_cert);
mbedtls_ssl_free(&ssl);
mbedtls_ssl_config_free(&conf);
}
下面是HTML解析的代码:
static int parse_time_from_title(const char *html, struct tm *out_tm)
{
const char *expires_start = strstr(html, "Expires: ");
if (expires_start) {
// 跳过 "Expires: " 前缀
expires_start += 9;
// 解析日期时间格式: Wed, 22 Oct 2025 21:07:4
char day[4], month[4];
int day_num, year, hour, min, sec;
if (sscanf(expires_start, "%3s, %d %3s %d %d:%d:%d",
day, &day_num, month, &year, &hour, &min, &sec) == 7) {
// 将月份名称转换为数字
int month_num = -1;
const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
for (int i = 0; i < 12; i++) {
if (strncmp(month, months[i], 3) == 0) {
month_num = i;
break;
}
}
if (month_num != -1) {
memset(out_tm, 0, sizeof(struct tm));
out_tm->tm_year = year - 1900;
out_tm->tm_mon = month_num;
out_tm->tm_mday = day_num;
out_tm->tm_hour = hour;
out_tm->tm_min = min;
out_tm->tm_sec = sec;
out_tm->tm_isdst = -1;
return 0;
}
}
}
return 0;
}
