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

基于Socket和线程的C语言Web服务器图片显示问题求助

C语言Socket线程Web服务器无法显示图片的解决方案

你的判断没错,无法显示图片的核心问题确实和Content-Type设置有关,同时还涉及二进制文件的读取和长度计算逻辑,以下是具体修复步骤:

1. 修复二进制文件读取方式

当前代码用文本模式("r")打开文件,会破坏图片这类二进制文件的内容;且用strlen()计算内容长度,图片中可能包含\0字节,导致长度计算错误。修改leeFichero函数:

// 替换全局变量定义
char *paginaCodigo = NULL;
size_t file_size;

int leeFichero(char *filename) {
    FILE *fit = fopen(filename, "rb"); // 用二进制模式打开文件
    if (fit == NULL) {
        printf("\n[Error]\tNo es pot obrir l'arxiu %s\n", filename);
        return 1;
    }

    // 获取文件实际大小
    fseek(fit, 0, SEEK_END);
    file_size = ftell(fit);
    fseek(fit, 0, SEEK_SET);

    // 动态分配内存存储文件内容
    paginaCodigo = malloc(file_size);
    if (!paginaCodigo) {
        perror("malloc failed");
        fclose(fit);
        return 1;
    }

    // 读取二进制内容
    fread(paginaCodigo, sizeof(char), file_size, fit);
    printf("Codi interior de l'arxiu (bytes:%zu)\n", file_size);
    fclose(fit);
    return 0;
}

2. 新增文件扩展名匹配MIME类型的函数

根据不同文件后缀返回对应的Content-Type,确保浏览器能正确解析图片:

const char* getContentType(const char* filename) {
    const char* ext = strrchr(filename, '.');
    if (!ext) return "application/octet-stream"; // 默认二进制类型

    if (strcmp(ext, ".html") == 0 || strcmp(ext, ".htm") == 0)
        return "text/html";
    else if (strcmp(ext, ".txt") == 0)
        return "text/plain";
    else if (strcmp(ext, ".jpg") == 0 || strcmp(ext, ".jpeg") == 0)
        return "image/jpeg";
    else if (strcmp(ext, ".png") == 0)
        return "image/png";
    else if (strcmp(ext, ".gif") == 0)
        return "image/gif";
    // 可根据需求添加更多类型(如.ico、svg等)
    return "application/octet-stream";
}

3. 修改响应发送函数,支持二进制内容

原sendResponse函数无法处理二进制内容,重新实现为分开发送响应头和二进制体:

void sendResponse(int sock, const char* content, size_t content_len, const char* content_type) {
    char header[512];
    // 拼接响应头
    int header_len = sprintf(header, "HTTP/1.1 200 OK\nContent-Type: %s\nContent-Length: %zu\n\n", content_type, content_len);
    
    // 先发送响应头
    send(sock, header, header_len, 0);
    // 再发送二进制文件内容
    send(sock, content, content_len, 0);
}

4. 调整请求处理逻辑

在creaMensaje函数中,调用新的响应函数,并添加内存释放逻辑:

if (!leeFichero(nomfichero)) {
    const char* content_type = getContentType(nomfichero);
    sendResponse(sock, paginaCodigo, file_size, content_type);
    free(paginaCodigo); // 释放动态分配的内存,避免泄漏
} else {
    const char* not_found = "<html><body><H1>404 Fitxer no trobat</H1></body></html>";
    sprintf(contenedor, "HTTP/1.1 404 Not Found\nContent-Type: text/html\nContent-Length: %zu\n\n%s", strlen(not_found), not_found);
    send(sock, contenedor, strlen(contenedor), 0);
}

额外优化点

  • 原代码中paginaCodigo固定3001字节,无法存储大尺寸图片,使用动态内存分配后可适配任意大小的文件(受限于系统内存)。
  • 可以添加文件存在性检查(用stat函数),提前判断文件是否存在,避免fopen失败。

内容的提问来源于stack exchange,提问作者Nikifor Ioan Tudor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 03:49:57