Pro*C(C语言)中无需openssl/libcurl的HTTPS请求实现示例咨询
不依赖libcurl、openssl的HTTPS请求实现方案(Pro*C适配)
方案选型说明
- ProC为Oracle提供的C语言内嵌SQL预编译环境,优先选择纯C实现、无外部动态依赖、可静态编译*的TLS协议栈,完全规避openssl、libcurl的编译和运行冲突
- 目前适配性最优的轻量实现为mbed TLS(原PolarSSL),可直接将源码放入项目目录编译,无需依赖系统预装的加密、网络库
- 若完全不想引入第三方源码,可直接调用系统自带的命令行工具发起HTTPS请求,零编译依赖
方案1:嵌入轻量TLS栈实现(稳定可控)
编译说明
将mbed TLS源码直接放入项目目录,和Pro*C生成的C代码一同编译即可,无需链接libcurl、libssl、libcrypto等系统动态库,可按需裁剪加密算法、TLS版本配置最小化编译体积。
代码示例(可直接嵌入.pc文件)
// 仅引入mbed TLS核心头文件,无openssl/curl依赖 #include "mbedtls/net_sockets.h" #include "mbedtls/ssl.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" #include "mbedtls/certs.h" #include <stdio.h> #include <string.h> #define HTTPS_PORT "443" #define REQUEST_HOST "example.com" #define REQUEST_PATH "/" #define REQUEST_BUF_SIZE 2048 #define RESPONSE_BUF_SIZE 4096 int https_request(void) { int ret; mbedtls_net_context server_fd; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; const char *pers = "pro_c_https_client"; unsigned char response_buf[RESPONSE_BUF_SIZE] = {0}; // 初始化上下文资源 mbedtls_net_init(&server_fd); mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); mbedtls_entropy_init(&entropy); mbedtls_ctr_drbg_init(&ctr_drbg); // 初始化随机数生成器 if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen(pers))) != 0) { goto clean_exit; } // 建立TCP连接 if((ret = mbedtls_net_connect(&server_fd, REQUEST_HOST, HTTPS_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) { goto clean_exit; } // 配置SSL参数 if((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { goto clean_exit; } // 证书校验配置,无需校验可设置为MBEDTLS_SSL_VERIFY_NONE mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_ca_chain(&conf, mbedtls_test_cas_pem, mbedtls_test_cas_pem_len); mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); if((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { goto clean_exit; } mbedtls_ssl_set_hostname(&ssl, REQUEST_HOST); mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); // 执行SSL握手 while((ret = mbedtls_ssl_handshake(&ssl)) != 0) { if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { goto clean_exit; } } // 构造GET请求 char request[REQUEST_BUF_SIZE] = {0}; snprintf(request, REQUEST_BUF_SIZE, "GET %s HTTP/1.1\r\n" "Host: %s\r\n" "Connection: close\r\n" "\r\n", REQUEST_PATH, REQUEST_HOST); // 发送请求 while((ret = mbedtls_ssl_write(&ssl, (const unsigned char *)request, strlen(request))) <= 0) { if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { goto clean_exit; } } // 读取响应 do { ret = mbedtls_ssl_read(&ssl, response_buf, RESPONSE_BUF_SIZE - 1); if(ret > 0) { // 此处可替换为业务逻辑处理响应内容 printf("%.*s", ret, response_buf); memset(response_buf, 0, RESPONSE_BUF_SIZE); } } while(ret > 0 || ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); ret = 0; clean_exit: // 释放所有资源 mbedtls_net_free(&server_fd); mbedtls_ssl_free(&ssl); mbedtls_ssl_config_free(&conf); mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); return ret; }
方案2:调用系统命令行实现(零编译依赖)
如果完全不想引入任何第三方源码,可直接调用系统预装的wget或curl命令行工具执行HTTPS请求,通过管道读取返回结果,无需修改项目编译配置:
#include <stdio.h> #include <string.h> int https_request_by_system_cmd(void) { FILE *cmd_fp; char buf[1024]; // 发起HTTPS GET请求,无需校验证书可添加 -k 参数 cmd_fp = popen("wget -qO- https://example.com", "r"); if(cmd_fp == NULL) { return -1; } while(fgets(buf, sizeof(buf), cmd_fp) != NULL) { // 此处可替换为业务逻辑处理响应内容 printf("%s", buf); } pclose(cmd_fp); return 0; }
Pro*C适配注意事项
- 上述两段纯C代码均可直接写入ProC的
.pc源文件中,ProC预编译时会完整保留C逻辑,无需特殊适配 - 方案1编译时,仅需将mbed TLS源码目录加入头文件搜索路径,关联对应
.o文件即可,不会引入openssl、libcurl的相关依赖 - 生产环境使用方案1时,建议替换内置的测试根证书为业务实际用到的根证书,降低安全风险
内容的提问来源于stack exchange,提问作者GomTang
相关产品推荐
相关产品推荐

