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

C语言WebServer处理GET请求无文件返回,报错curl: (52) Empty reply from server

问题分析与修复

你的代码存在几个关键错误,直接导致客户端收到空响应:

  • 错误的send调用逻辑
    你用send(client_fd, &opened_fd, 256, NULL)把文件描述符的内存地址发给了客户端,这完全不是文件内容。而且send的第四个参数是flags,必须传整数(比如0),不能传NULL。

  • sendfile参数顺序错误(且未正确使用)
    注释掉的sendfile调用参数顺序搞反了,正确的sendfile语法是:

    ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
    

    应当把客户端套接字fd(client_fd)放在第一个参数,打开的文件fd(opened_fd)放在第二个参数。同时你传的0意味着发送0字节,自然没有内容返回。

  • 缺失错误检查
    socket、bind、listen、accept、recv、open这些系统调用都可能失败,你没有检查它们的返回值。比如如果index.html不存在,open会返回-1,后续操作全错。

  • 未处理请求格式异常
    如果收到的请求不符合GET /file ...格式,strchr(f, ' ')会返回NULL,直接解引用*strchr(f, ' ')会导致程序崩溃。


修复后的代码示例

#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>

int main() {
    int s = socket(AF_INET, SOCK_STREAM, 0);
    if (s == -1) {
        perror("socket failed");
        return 1;
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8080);
    addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
        perror("bind failed");
        close(s);
        return 1;
    }

    if (listen(s, 10) == -1) {
        perror("listen failed");
        close(s);
        return 1;
    }

    int client_fd = accept(s, NULL, NULL);
    if (client_fd == -1) {
        perror("accept failed");
        close(s);
        return 1;
    }

    char buffer[256] = {0};
    ssize_t recv_len = recv(client_fd, buffer, sizeof(buffer)-1, 0);
    if (recv_len <= 0) {
        perror("recv failed or client closed");
        close(client_fd);
        close(s);
        return 1;
    }

    // 解析请求路径
    char* f = buffer + 5;
    char* space_ptr = strchr(f, ' ');
    if (!space_ptr) {
        fprintf(stderr, "Invalid request format\n");
        close(client_fd);
        close(s);
        return 1;
    }
    *space_ptr = '\0';

    // 打开文件
    int opened_fd = open(f, O_RDONLY);
    if (opened_fd == -1) {
        perror("open file failed");
        close(client_fd);
        close(s);
        return 1;
    }

    // 获取文件大小
    struct stat file_stat;
    if (fstat(opened_fd, &file_stat) == -1) {
        perror("fstat failed");
        close(opened_fd);
        close(client_fd);
        close(s);
        return 1;
    }

    // 使用sendfile发送文件内容
    ssize_t sent = sendfile(client_fd, opened_fd, NULL, file_stat.st_size);
    if (sent == -1) {
        perror("sendfile failed");
    }

    // 关闭资源
    close(opened_fd);
    close(client_fd);
    close(s);
    return 0;
}

额外说明

  1. 运行修复后的代码后,再执行curl --http0.9 --output - 'http://localhost:8080/index.html'就能正确获取文件内容了。
  2. 如果你不想用sendfile,也可以用read读取文件内容到缓冲区,再用send发送给客户端,逻辑类似。
  3. 生产环境的Web服务器需要处理更多情况(比如并发请求、不同HTTP方法、错误响应等),但这个修复能解决当前的空响应问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 23:23:10