You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于OpenSSL的C客户端无法显示HTTP响应体内容问题

问题分析与解决方案

你的C客户端仅读取到HTTP响应头、无法获取响应体的核心原因是仅调用了一次SSL_read。TCP是流式传输协议,服务器的响应可能分多个TCP段发送,单次SSL_read只能获取当前到达的数据,无法保证一次性拿到完整的响应头+响应体。

具体问题点

  • 未校验SSL_connect返回值:若SSL握手失败,后续读写操作都会异常,但代码直接跳过了结果判断
  • 未确认SSL_write是否发送完整请求:如果请求未全部送达服务器,可能导致响应不完整
  • 单次SSL_read无法覆盖所有响应数据:即使缓冲区足够大,数据也可能分批到达,需要循环读取

修复后的代码示例

// 检查SSL握手是否成功
if (SSL_connect(ssl) != 1) {
    printf("[-] SSL_connect() failed\n");
    return -1;
}

char *request = "GET / HTTP/1.1\r\nHost: webapp_ip:XXXX\r\nUser-Agent: TOPG\r\nAccept-Encoding: gzip, deflate, br\r\nConnection: keep-alive\r\n\r\n";
int req_len = strlen(request);
int sent = SSL_write(ssl, request, req_len);
// 确认请求是否完全发送
if (sent != req_len) {
    printf("[-] SSL_write() sent only %d of %d bytes\n", sent, req_len);
    return -1;
}

char buf[8192] = {0};
int total_received = 0;
int content_length = -1;
char *content_len_ptr;

// 第一步:循环读取直到拿到完整响应头,解析Content-Length
while (1) {
    int received = SSL_read(ssl, buf + total_received, sizeof(buf) - total_received - 1);
    if (received <= 0) {
        printf("[-] SSL_read() failed or connection closed\n");
        return -1;
    }
    total_received += received;
    buf[total_received] = '\0'; // 确保字符串可被解析

    // 检测响应头结束标记:\r\n\r\n
    if (strstr(buf, "\r\n\r\n") != NULL) {
        // 提取Content-Length值
        content_len_ptr = strstr(buf, "Content-Length: ");
        if (content_len_ptr != NULL) {
            content_length = atoi(content_len_ptr + 16); // "Content-Length: "长度为16
        }
        break;
    }
}

// 第二步:根据Content-Length读取完整响应体
if (content_length > 0) {
    int body_received = 0;
    char *body_buf = buf + total_received;
    int remaining_buf = sizeof(buf) - total_received;

    while (body_received < content_length) {
        int need_read = content_length - body_received;
        int read_size = (need_read < remaining_buf) ? need_read : remaining_buf;

        int received = SSL_read(ssl, body_buf, read_size);
        if (received <= 0) {
            printf("[-] Failed to read response body\n");
            return -1;
        }

        body_received += received;
        body_buf += received;
        remaining_buf -= received;
    }

    total_received += body_received;
    buf[total_received] = '\0';
}

printf("Total received [%d] \n%s\n", total_received, buf);

额外说明

  • 你的Flask代码存在小问题:puts(colored.yellow(str(request.headers)))需改为print(colored.yellow(str(request.headers))),且需提前导入colored库(from colored import colored),但此问题不影响响应体返回
  • 由于请求中设置了Connection: keep-alive,服务器不会主动关闭连接,因此必须通过Content-Length确定响应体长度,不能依赖SSL_read返回0判断结束

内容的提问来源于stack exchange,提问作者misha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 10:55:12