基于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
相关产品推荐
相关产品推荐

