如何用C语言构建Linux本地HTTP 1.1服务器,返回200响应并发送index.html
用C语言实现Linux下HTTP/1.1 Web服务器发送HTML响应的方法
你的代码目前存在几个不符合HTTP/1.1规范的问题,导致无法正确返回HTML内容,下面是修正方案和关键说明:
原代码的核心问题
- 协议版本用了
HTTP/1.0,但需求是HTTP/1.1 Content-Length写死为2048,和实际文件大小不匹配,会导致客户端解析异常- 缺少HTTP/1.1要求的必要响应头(比如
Date、Connection、Content-Type) - 响应头的换行用了单个换行符,HTTP标准要求必须是
\r\n,且响应头和正文之间需要空一行(两个\r\n)
修正后的完整代码
#include <stdio.h> #include <string.h> #include <sys/socket.h> #include <sys/stat.h> #include <time.h> // 发送错误响应(404 Not Found) void send_error(int s) { char error_response[] = "HTTP/1.1 404 Not Found\r\n" "Server: Linux Web Server\r\n" "Date: %s\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" "Content-Length: 135\r\n" "\r\n" "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" "<html><head><title>404 Not Found</title></head>\n" "<body><h1>Not Found</h1><p>The requested URL was not found on this server.</p></body></html>\n"; // 生成符合HTTP格式的日期字符串 char date_buf[64]; time_t now = time(NULL); struct tm *tm_info = gmtime(&now); strftime(date_buf, sizeof(date_buf), "%a, %d %b %Y %H:%M:%S GMT", tm_info); char full_response[512]; sprintf(full_response, error_response, date_buf); send(s, full_response, strlen(full_response), 0); } // 发送HTML文件的正确响应 void send_data(int s, char *path) { // path='/index.html' char buf[1024]; char filename[256]; FILE *send_file; struct stat file_stat; // 拼接文件路径 sprintf(filename, "htdocs%s", path); // 获取文件状态,用于获取文件大小 if (stat(filename, &file_stat) != 0) { send_error(s); return; } // 打开文件 send_file = fopen(filename, "rb"); if (send_file == NULL) { send_error(s); return; } // 生成HTTP响应头 char response_header[512]; char date_buf[64]; time_t now = time(NULL); struct tm *tm_info = gmtime(&now); strftime(date_buf, sizeof(date_buf), "%a, %d %b %Y %H:%M:%S GMT", tm_info); sprintf(response_header, "HTTP/1.1 200 OK\r\n" "Server: Linux Web Server\r\n" "Date: %s\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" "Content-Length: %ld\r\n" "\r\n", date_buf, file_stat.st_size ); // 发送响应头 send(s, response_header, strlen(response_header), 0); // 发送文件内容 int len; while ((len = fread(buf, 1, sizeof(buf), send_file)) > 0) { send(s, buf, len, 0); } fclose(send_file); }
关键要点说明
- HTTP/1.1协议合规:响应头开头明确用
HTTP/1.1 200 OK,所有头字段用\r\n分隔,头和正文之间用空行(\r\n\r\n)分隔 - 动态计算Content-Length:通过
stat函数获取文件的真实大小,避免写死数值导致的解析错误 - 添加必要响应头:
Date:必须包含的HTTP头,用GMT格式的当前时间Connection: close:告诉客户端响应结束后关闭连接(适合简单服务器)Content-Type: text/html:明确告诉客户端返回的是HTML内容
- 错误处理完善:无论是文件不存在还是打开失败,都返回标准的404错误响应
- 文件读取优化:用二进制模式打开文件,避免文本模式下的换行符转换问题,确保文件内容完整发送
内容的提问来源于stack exchange,提问作者amsd
相关产品推荐
相关产品推荐

