edge不能上网-代码 INET_E_RESOURCE_NOT_FOUND

本文分享了解决在代理环境中浏览器无法正常使用的问题经验。作者在遇到该问题后尝试多种解决方案,最终通过调整浏览器配置得以解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个问题 ,网上有很多解决方法,我基本都测试了一遍,可是我都没有用

情况:首先,我开始的时候是可以用的,然后在公司,开了代理,就不能使用了,这是我之后多次尝试发现的,所以你也遇到和我一样的情况不必惊慌,你可以换个浏览器用呗,这是最简单的,

但是如果你已经很习惯这个浏览器的话,你可能会很纠结,我个人只是觉得好玩,所以花了点时间弄了一下,其实很简单,

 

 

然后你配置一下就ok了

转载于:https://www.cnblogs.com/yang1com/p/10649918.html

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/epoll.h> #include <fcntl.h> #include <sys/stat.h> #include <dirent.h> #include <time.h> #include <errno.h> #include <ctype.h> #include <signal.h> #define MAX_EVENTS 1024 #define BUFFER_SIZE 4096 #define SERVER_STRING "Server: jdbhttpd/0.4.0 (epoll)\r\n" #define ISspace(x) isspace((int)(x)) #define CONNECTION_TIMEOUT 30 // 连接超时时间(秒) // 连接状态结构体 typedef struct { int fd; // 文件描述符 char buffer[BUFFER_SIZE]; // 读写缓冲区 size_t buffer_len; // 缓冲区数据长度 size_t buffer_sent; // 已发送字节数 int file_fd; // 打开的文件描述符 off_t file_size; // 文件大小 off_t file_sent; // 已发送文件字节数 char method[16]; // HTTP方法 char url[1024]; // 请求URL char path[2048]; // 文件路径 int response_code; // 响应状态码 int content_length; // 内容长度 time_t last_activity; // 最后活动时间 } connection_t; // 函数声明 void set_nonblocking(int sock); void handle_request(connection_t *conn); void send_response(connection_t *conn); void send_headers(connection_t *conn); void send_file(connection_t *conn); void close_connection(connection_t *conn); void log_request(connection_t *conn); const char *get_mime_type(const char *filename); void url_decode(char *dest, const char *src); void serve_directory(int client, const char *path); void not_found(connection_t *conn); void bad_request(connection_t *conn); void unimplemented(connection_t *conn); void forbidden(connection_t *conn); int startup(unsigned short *port); // 设置非阻塞 void set_nonblocking(int sock) { int flags = fcntl(sock, F_GETFL, 0); fcntl(sock, F_SETFL, flags | O_NONBLOCK); } // 启动服务器 int startup(unsigned short *port) { int httpd = socket(PF_INET, SOCK_STREAM, 0); if (httpd == -1) { perror("socket"); exit(1); } int opt = 1; if (setsockopt(httpd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { perror("setsockopt"); close(httpd); exit(1); } struct sockaddr_in name; memset(&name, 0, sizeof(name)); name.sin_family = AF_INET; name.sin_port = htons(*port); name.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(httpd, (struct sockaddr *)&name, sizeof(name)) < 0) { perror("bind"); close(httpd); exit(1); } if (*port == 0) { socklen_t namelen = sizeof(name); if (getsockname(httpd, (struct sockaddr *)&name, &namelen) == -1) { perror("getsockname"); close(httpd); exit(1); } *port = ntohs(name.sin_port); } if (listen(httpd, 1024) < 0) { perror("listen"); close(httpd); exit(1); } return httpd; } // URL解码 void url_decode(char *dest, const char *src) { char *p = dest; while (*src) { if (*src == '%') { if (src[1] && src[2]) { char hex[3] = {src[1], src[2], '\0'}; *p++ = (char)strtol(hex, NULL, 16); src += 3; } else { *p++ = *src++; } } else if (*src == '+') { *p++ = ' '; src++; } else { *p++ = *src++; } } *p = '\0'; } // 获取MIME类型 const char *get_mime_type(const char *filename) { const char *dot = strrchr(filename, '.'); if (!dot) return "text/plain"; if (strcasecmp(dot, ".html") == 0 || strcasecmp(dot, ".htm") == 0) return "text/html"; if (strcasecmp(dot, ".css") == 0) return "text/css"; if (strcasecmp(dot, ".js") == 0) return "application/javascript"; if (strcasecmp(dot, ".jpg") == 0 || strcasecmp(dot, ".jpeg") == 0) return "image/jpeg"; if (strcasecmp(dot, ".png") == 0) return "image/png"; if (strcasecmp(dot, ".gif") == 0) return "image/gif"; if (strcasecmp(dot, ".json") == 0) return "application/json"; if (strcasecmp(dot, ".ico") == 0) return "image/x-icon"; return "text/plain"; } // 记录请求日志 void log_request(connection_t *conn) { time_t now = time(NULL); struct tm *tm = localtime(&now); char timestamp[64]; strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", tm); struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); getpeername(conn->fd, (struct sockaddr*)&addr, &addr_len); char *ip = inet_ntoa(addr.sin_addr); printf("[%s] %s %s %s %d\n", timestamp, ip, conn->method, conn->url, conn->response_code); } // 处理目录列表 void serve_directory(int client, const char *path) { char buf[BUFFER_SIZE]; // 发送HTTP头 sprintf(buf, "HTTP/1.0 200 OK\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, SERVER_STRING); send(client, buf, strlen(buf), 0); sprintf(buf, "Content-Type: text/html\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, "\r\n"); send(client, buf, strlen(buf), 0); // 发送HTML头部 sprintf(buf, "<html><head><title>Index of %s</title></head>", path); send(client, buf, strlen(buf), 0); sprintf(buf, "<body><h1>Index of %s</h1><ul>", path); send(client, buf, strlen(buf), 0); // 打开目录 DIR *dir = opendir(path); if (dir) { struct dirent *ent; while ((ent = readdir(dir)) != NULL) { // 跳过隐藏文件 if (ent->d_name[0] == '.') continue; char full_path[2048]; sprintf(full_path, "%s/%s", path, ent->d_name); struct stat st; stat(full_path, &st); char size_buf[32]; if (S_ISDIR(st.st_mode)) { strcpy(size_buf, "[DIR]"); } else { if (st.st_size < 1024) { sprintf(size_buf, "%ld B", st.st_size); } else if (st.st_size < 1024 * 1024) { sprintf(size_buf, "%.1f KB", st.st_size / 1024.0); } else { sprintf(size_buf, "%.1f MB", st.st_size / (1024.0 * 1024)); } } sprintf(buf, "<li><a href=\"%s\">%s</a> - %s</li>", ent->d_name, ent->d_name, size_buf); send(client, buf, strlen(buf), 0); } closedir(dir); } // 发送HTML尾部 sprintf(buf, "</ul></body></html>\r\n"); send(client, buf, strlen(buf), 0); } // 处理请求 void handle_request(connection_t *conn) { char *buf = conn->buffer; size_t len = conn->buffer_len; // 解析请求行 int i = 0, j = 0; while (!ISspace(buf[j]) && (i < sizeof(conn->method) - 1) && (j < len)) { conn->method[i] = buf[j]; i++; j++; } conn->method[i] = '\0'; // 只支持GET方法 if (strcasecmp(conn->method, "GET") && strcasecmp(conn->method, "POST")&& strcasecmp(conn->method, "HEAD")) { unimplemented(conn); return; } // 读取URL i = 0; while (ISspace(buf[j]) && (j < len)) j++; while (!ISspace(buf[j]) && (i < sizeof(conn->url) - 1) && (j < len)) { conn->url[i] = buf[j]; i++; j++; } conn->url[i] = '\0'; // URL解码 char decoded_url[1024]; url_decode(decoded_url, conn->url); // 构建文件路径 - 添加web前缀 snprintf(conn->path, sizeof(conn->path), "web%s", decoded_url); // 防止路径遍历攻击 if (strstr(conn->path, "..")) { forbidden(conn); return; } // 处理目录请求: 如果路径以'/'结尾,则添加Index.html size_t path_len = strlen(conn->path); if (path_len > 0 && conn->path[path_len - 1] == '/') { strncat(conn->path, "Index.html", sizeof(conn->path) - path_len - 1); } // 检查文件/目录是否存在 struct stat st; if (stat(conn->path, &st) == -1) { // 尝试添加.html扩展名(仅对无扩展名的路径) if (!strrchr(conn->path, '.')) { char alt_path[2048]; snprintf(alt_path, sizeof(alt_path), "%s.html", conn->path); if (stat(alt_path, &st) == 0) { strcpy(conn->path, alt_path); } else { not_found(conn); return; } } else { not_found(conn); return; } } // 如果是目录 if (S_ISDIR(st.st_mode)) { // 检查目录中是否有index.html char index_path[2048]; snprintf(index_path, sizeof(index_path), "%s/Index.html", conn->path); if (stat(index_path, &st) == 0) { strcpy(conn->path, index_path); } else { // 显示目录列表 serve_directory(conn->fd, conn->path); conn->response_code = 200; return; } } // 打开文件 conn->file_fd = open(conn->path, O_RDONLY); if (conn->file_fd == -1) { if (errno == EACCES) { forbidden(conn); } else { not_found(conn); } return; } // 获取文件信息 if (fstat(conn->file_fd, &st) == -1) { close(conn->file_fd); not_found(conn); return; } conn->file_size = st.st_size; conn->file_sent = 0; conn->response_code = 200; // 准备响应头 send_headers(conn); } // 发送响应头 void send_headers(connection_t *conn) { char buf[BUFFER_SIZE]; const char *content_type = get_mime_type(conn->path); // 发送状态行 if (conn->response_code == 200) { sprintf(buf, "HTTP/1.0 200 OK\r\n"); } else if (conn->response_code == 404) { sprintf(buf, "HTTP/1.0 404 Not Found\r\n"); } else if (conn->response_code == 400) { sprintf(buf, "HTTP/1.0 400 Bad Request\r\n"); } else if (conn->response_code == 403) { sprintf(buf, "HTTP/1.0 403 Forbidden\r\n"); } else if (conn->response_code == 501) { sprintf(buf, "HTTP/1.0 501 Not Implemented\r\n"); } else { sprintf(buf, "HTTP/1.0 500 Internal Server Error\r\n"); } // 计算头部长度 conn->buffer_len = 0; conn->buffer_sent = 0; // 状态行 size_t len = strlen(buf); memcpy(conn->buffer + conn->buffer_len, buf, len); conn->buffer_len += len; // Server头 len = strlen(SERVER_STRING); memcpy(conn->buffer + conn->buffer_len, SERVER_STRING, len); conn->buffer_len += len; // Content-Type头 sprintf(buf, "Content-Type: %s\r\n", content_type); len = strlen(buf); memcpy(conn->buffer + conn->buffer_len, buf, len); conn->buffer_len += len; // Content-Length头 if (conn->response_code == 200) { sprintf(buf, "Content-Length: %ld\r\n", conn->file_size); } else { sprintf(buf, "Content-Length: %zu\r\n", conn->buffer_len); } len = strlen(buf); memcpy(conn->buffer + conn->buffer_len, buf, len); conn->buffer_len += len; // Connection头 sprintf(buf, "Connection: close\r\n"); len = strlen(buf); memcpy(conn->buffer + conn->buffer_len, buf, len); conn->buffer_len += len; // 结束头部 sprintf(buf, "\r\n"); len = strlen(buf); memcpy(conn->buffer + conn->buffer_len, buf, len); conn->buffer_len += len; // 对于非200响应,错误信息已经在buffer中 if (conn->response_code != 200) { conn->file_fd = -1; // 不需要发送文件 } } // 发送响应 void send_response(connection_t *conn) { // 更新活动时间 conn->last_activity = time(NULL); // 发送头部 if (conn->buffer_sent < conn->buffer_len) { ssize_t sent = send(conn->fd, conn->buffer + conn->buffer_sent, conn->buffer_len - conn->buffer_sent, MSG_NOSIGNAL); if (sent < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK) { close_connection(conn); return; } } else { conn->buffer_sent += sent; } // 头部尚未发送完成 if (conn->buffer_sent < conn->buffer_len) { return; } } // 发送文件内容 if (conn->file_fd != -1 && conn->file_sent < conn->file_size) { // 使用sendfile系统调用提高效率 off_t offset = conn->file_sent; ssize_t sent = sendfile(conn->fd, conn->file_fd, &offset, conn->file_size - conn->file_sent); if (sent < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // 可重试的错误 return; } perror("sendfile failed"); close_connection(conn); return; } else if (sent == 0) { // 文件结束 conn->file_sent = conn->file_size; } else { conn->file_sent += sent; } } // 检查是否完成 if (conn->file_fd == -1 || conn->file_sent >= conn->file_size) { close_connection(conn); } } // 404 Not Found void not_found(connection_t *conn) { conn->response_code = 404; const char *response = "<html><body><h1>404 Not Found</h1>" "<p>The requested URL was not found on this server.</p></body></html>\r\n"; conn->buffer_len = snprintf(conn->buffer, sizeof(conn->buffer), "%s", response); send_headers(conn); } // 400 Bad Request void bad_request(connection_t *conn) { conn->response_code = 400; const char *response = "<html><body><h1>400 Bad Request</h1></body></html>\r\n"; conn->buffer_len = snprintf(conn->buffer, sizeof(conn->buffer), "%s", response); send_headers(conn); } // 403 Forbidden void forbidden(connection_t *conn) { conn->response_code = 403; const char *response = "<html><body><h1>403 Forbidden</h1>" "<p>Access to this resource is denied.</p></body></html>\r\n"; conn->buffer_len = snprintf(conn->buffer, sizeof(conn->buffer), "%s", response); send_headers(conn); } // 501 Not Implemented void unimplemented(connection_t *conn) { conn->response_code = 501; const char *response = "<html><body><h1>501 Not Implemented</h1>" "<p>The requested method is not implemented.</p></body></html>\r\n"; conn->buffer_len = snprintf(conn->buffer, sizeof(conn->buffer), "%s", response); send_headers(conn); } // 关闭连接 void close_connection(connection_t *conn) { log_request(conn); if (conn->file_fd != -1) { close(conn->file_fd); } close(conn->fd); free(conn); } int main(void) { unsigned short port = 8080; int server_sock = startup(&port); printf("HTTP server (epoll) running on port %d\n", port); // 设置非阻塞 set_nonblocking(server_sock); // 创建epoll实例 int epoll_fd = epoll_create1(0); if (epoll_fd == -1) { perror("epoll_create1"); close(server_sock); exit(1); } // 添加服务器socket到epoll struct epoll_event event; event.events = EPOLLIN | EPOLLET; event.data.ptr = NULL; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_sock, &event) == -1) { perror("epoll_ctl: server_sock"); close(server_sock); close(epoll_fd); exit(1); } // 事件循环 struct epoll_event events[MAX_EVENTS]; time_t last_timeout_check = time(NULL); while (1) { int timeout_ms = 1000; // 1秒超时 int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, timeout_ms); if (nfds == -1) { perror("epoll_wait"); continue; } // 定期检查超时连接 time_t now = time(NULL); if (now - last_timeout_check > 5) { // 每5秒检查一次 // 在实际应用中,这里需要遍历所有连接检查超时 last_timeout_check = now; } for (int i = 0; i < nfds; i++) { // 处理新连接 if (events[i].data.ptr == NULL) { struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); int client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_len); if (client_sock == -1) { if (errno != EAGAIN && errno != EWOULDBLOCK) { perror("accept"); } continue; } // 设置非阻塞 set_nonblocking(client_sock); // 创建连接结构体 connection_t *conn = calloc(1, sizeof(connection_t)); if (!conn) { perror("calloc"); close(client_sock); continue; } conn->fd = client_sock; conn->file_fd = -1; conn->last_activity = time(NULL); // 记录活动时间 // 添加到epoll struct epoll_event ev; ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP; ev.data.ptr = conn; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_sock, &ev) == -1) { perror("epoll_ctl: client_sock"); close(client_sock); free(conn); } } else { // 处理客户端事件 connection_t *conn = events[i].data.ptr; // 检查连接是否关闭 if (events[i].events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR)) { close_connection(conn); continue; } if (events[i].events & EPOLLIN) { // 更新活动时间 conn->last_activity = time(NULL); // 读取数据 ssize_t count = recv(conn->fd, conn->buffer + conn->buffer_len, sizeof(conn->buffer) - conn->buffer_len - 1, 0); if (count > 0) { conn->buffer_len += count; conn->buffer[conn->buffer_len] = '\0'; // 检查是否收到完整请求 if (strstr(conn->buffer, "\r\n\r\n") != NULL) { // 处理请求 handle_request(conn); // 修改为监听写事件 struct epoll_event ev; ev.events = EPOLLOUT | EPOLLET | EPOLLRDHUP; ev.data.ptr = conn; if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, conn->fd, &ev) == -1) { perror("epoll_ctl: mod write"); close_connection(conn); } } } else if (count == 0 || (count < 0 && errno != EAGAIN && errno != EWOULDBLOCK)) { // 连接关闭或出错 close_connection(conn); } } else if (events[i].events & EPOLLOUT) { // 发送响应 send_response(conn); } } } } close(server_sock); close(epoll_fd); return 0; } 目前版本如上 存在的问题:只能响应一个浏览器页面,当另一个浏览器页面同时访问后将无法正常加载,关闭后仍然无法正常响应
最新发布
08-12
#include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netinet/tcp.h> #include <arpa/inet.h> #include <unistd.h> #include <ctype.h> #include <strings.h> #include <string.h> #include <sys/stat.h> #include <pthread.h> #include <sys/wait.h> #include <stdlib.h> #include <dirent.h> #include <time.h> #define ISspace(x) isspace((int)(x)) #define SERVER_STRING "Server: jdbhttpd/0.2.0\r\n" // 函数声明 void* accept_request(void *); void bad_request(int); void cat(int, FILE *); void cannot_execute(int); void error_die(const char *); int get_line(int, char *, int); void headers(int, const char *, const char *); void not_found(int); void serve_file(int, const char *); int startup(unsigned short *); void unimplemented(int); void forbidden(int); void serve_directory(int, const char *); void url_decode(char *, const char *); const char *get_mime_type(const char *); void log_request(const char *, const char *, int); void set_socket_timeout(int, int); /**********************************************************************/ /* 处理客户端请求 */ /**********************************************************************/ void* accept_request(void *pclient) { int client = *(int*)pclient; free(pclient); set_socket_timeout(client, 2); char buf[65536]; int numchars; char method[255]; char url[255]; char path[1024]; // 增加路径长度 char decoded_url[1024]; // 存储解码后的URL size_t i, j; struct stat st; // 获取请求的第一行 numchars = get_line(client, buf, sizeof(buf)); i = 0; j = 0; while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) { method[i] = buf[j]; i++; j++; } method[i] = '\0'; // 只支持GET和POST方法 if (strcasecmp(method, "GET") && strcasecmp(method, "POST") && strcasecmp(method, "OPTIONS")) { unimplemented(client); return NULL; } // 读取URL i = 0; while (ISspace(buf[j]) && (j < sizeof(buf))) j++; while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) { url[i] = buf[j]; i++; j++; } url[i] = '\0'; // URL解码 url_decode(decoded_url, url); // 记录请求日志 log_request(method, decoded_url, client); // 构建文件路径(使用当前目录) sprintf(path, "web%s", decoded_url); // 防止路径遍历攻击 if (strstr(path, "..")) { forbidden(client); close(client); return NULL; } // 处理目录请求 if (path[strlen(path) - 1] == '/') strcat(path, "Index.html"); // 检查文件/目录是否存在 if (stat(path, &st) == -1) { // 检查是否存在.html扩展名文件 char alt_path[1024]; sprintf(alt_path, "%s.html", path); if (stat(alt_path, &st) == 0) { strcpy(path, alt_path); } else { /* 跳过剩余头部 */ while ((numchars > 0) && strcmp("\n", buf)) numchars = get_line(client, buf, sizeof(buf)); not_found(client); close(client); return NULL; } } // 如果是目录 if ((st.st_mode & S_IFMT) == S_IFDIR) { // 检查目录中是否有index.html char index_path[1024]; sprintf(index_path, "%s/Index.html", path); if (stat(index_path, &st) == 0) { strcpy(path, index_path); } else { // 显示目录列表 serve_directory(client, path); close(client); return NULL; } } serve_file(client, path); close(client); return NULL; } /**********************************************************************/ /* URL解码 */ /**********************************************************************/ void url_decode(char *dest, const char *src) { char *p = dest; while (*src) { if (*src == '%') { if (src[1] && src[2]) { char hex[3] = {src[1], src[2], '\0'}; *p++ = (char)strtol(hex, NULL, 16); src += 3; } else { *p++ = *src++; } } else if (*src == '+') { *p++ = ' '; src++; } else { *p++ = *src++; } } *p = '\0'; } /**********************************************************************/ /* 获取MIME类型 */ /**********************************************************************/ const char *get_mime_type(const char *filename) { const char *dot = strrchr(filename, '.'); if (!dot) return "text/plain"; if (strcasecmp(dot, ".html") == 0 || strcasecmp(dot, ".htm") == 0) return "text/html"; if (strcasecmp(dot, ".css") == 0) return "text/css"; if (strcasecmp(dot, ".js") == 0) return "application/javascript"; if (strcasecmp(dot, ".jpg") == 0 || strcasecmp(dot, ".jpeg") == 0) return "image/jpeg"; if (strcasecmp(dot, ".png") == 0) return "image/png"; if (strcasecmp(dot, ".gif") == 0) return "image/gif"; if (strcasecmp(dot, ".json") == 0) return "application/json"; if (strcasecmp(dot, ".ico") == 0) return "image/x-icon"; return "text/plain"; } /**********************************************************************/ /* 记录请求日志 */ /**********************************************************************/ void log_request(const char *method, const char *url, int client) { time_t now = time(NULL); struct tm *tm = localtime(&now); char timestamp[64]; strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", tm); struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); getpeername(client, (struct sockaddr*)&addr, &addr_len); char *ip = inet_ntoa(addr.sin_addr); printf("[%s] %s %s %s\n", timestamp, ip, method, url); } /**********************************************************************/ /* 处理目录列表 */ /**********************************************************************/ void serve_directory(int client, const char *path) { char buf[4096]; // 发送HTTP头 sprintf(buf, "HTTP/1.0 200 OK\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, SERVER_STRING); send(client, buf, strlen(buf), 0); sprintf(buf, "Content-Type: text/html\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, "\r\n"); send(client, buf, strlen(buf), 0); // 发送HTML头部 sprintf(buf, "<html><head><title>Index of %s</title></head>", path); send(client, buf, strlen(buf), 0); sprintf(buf, "<body><h1>Index of %s</h1><ul>", path); send(client, buf, strlen(buf), 0); // 打开目录 DIR *dir = opendir(path); if (dir) { struct dirent *ent; while ((ent = readdir(dir)) != NULL) { // 跳过隐藏文件 if (ent->d_name[0] == '.') continue; char full_path[1024]; sprintf(full_path, "%s/%s", path, ent->d_name); struct stat st; stat(full_path, &st); char size_buf[32]; if (S_ISDIR(st.st_mode)) { strcpy(size_buf, "[DIR]"); } else { if (st.st_size < 1024) { sprintf(size_buf, "%ld B", st.st_size); } else if (st.st_size < 1024 * 1024) { sprintf(size_buf, "%.1f KB", st.st_size / 1024.0); } else { sprintf(size_buf, "%.1f MB", st.st_size / (1024.0 * 1024)); } } sprintf(buf, "<li><a href=\"%s\">%s</a> - %s</li>", ent->d_name, ent->d_name, size_buf); send(client, buf, strlen(buf), 0); } closedir(dir); } // 发送HTML尾部 sprintf(buf, "</ul></body></html>\r\n"); send(client, buf, strlen(buf), 0); } /**********************************************************************/ /* 400 Bad Request */ /**********************************************************************/ void bad_request(int client) { char buf[1024]; sprintf(buf, "HTTP/1.0 400 BAD REQUEST\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, "Content-type: text/html\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, "\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, "<html><body><h1>400 Bad Request</h1></body></html>\r\n"); send(client, buf, strlen(buf), 0); } /**********************************************************************/ /* 403 Forbidden */ /**********************************************************************/ void forbidden(int client) { char buf[1024]; sprintf(buf, "HTTP/1.0 403 Forbidden\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, SERVER_STRING); send(client, buf, strlen(buf), 0); sprintf(buf, "Content-Type: text/html\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, "\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, "<html><body><h1>403 Forbidden</h1><p>Access to this resource is denied.</p></body></html>\r\n"); send(client, buf, strlen(buf), 0); } /**********************************************************************/ /* 发送文件内容 */ /**********************************************************************/ void cat(int client, FILE *resource) { char buf[65536]; fgets(buf, sizeof(buf), resource); while (!feof(resource)) { send(client, buf, strlen(buf), 0); fgets(buf, sizeof(buf), resource); } } /**********************************************************************/ /* 500 Internal Server Error */ /**********************************************************************/ void cannot_execute(int client) { char buf[1024]; sprintf(buf, "HTTP/1.0 500 Internal Server Error\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, "Content-type: text/html\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, "\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, "<html><body><h1>500 Internal Server Error</h1><p>CGI execution failed.</p></body></html>\r\n"); send(client, buf, strlen(buf), 0); } /**********************************************************************/ /* 错误处理 */ /**********************************************************************/ void error_die(const char *sc) { perror(sc); exit(1); } /**********************************************************************/ /* 读取一行 */ /**********************************************************************/ int get_line(int sock, char *buf, int size) { int i = 0; char c = '\0'; int n; while ((i < size - 1) && (c != '\n')) { n = recv(sock, &c, 1, 0); if (n > 0) { if (c == '\r') { n = recv(sock, &c, 1, MSG_PEEK); if ((n > 0) && (c == '\n')) recv(sock, &c, 1, 0); else c = '\n'; } buf[i] = c; i++; } else c = '\n'; } buf[i] = '\0'; return(i); } /**********************************************************************/ /* 发送HTTP头 */ /**********************************************************************/ void headers(int client, const char *filename, const char *content_type) { char buf[1024]; (void)filename; // 未使用 strcpy(buf, "HTTP/1.0 200 OK\r\n"); send(client, buf, strlen(buf), 0); strcpy(buf, SERVER_STRING); send(client, buf, strlen(buf), 0); sprintf(buf, "Content-Type: %s\r\n", content_type); send(client, buf, strlen(buf), 0); strcpy(buf, "\r\n"); send(client, buf, strlen(buf), 0); } /**********************************************************************/ /* 404 Not Found */ /**********************************************************************/ void not_found(int client) { char buf[1024]; sprintf(buf, "HTTP/1.0 404 NOT FOUND\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, SERVER_STRING); send(client, buf, strlen(buf), 0); sprintf(buf, "Content-Type: text/html\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, "\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, "<html><body><h1>404 Not Found</h1><p>The requested URL was not found on this server.</p></body></html>\r\n"); send(client, buf, strlen(buf), 0); } /**********************************************************************/ /* 服务静态文件(修复二进制文件处理) */ /**********************************************************************/ void serve_file(int client, const char *filename) { FILE *resource = NULL; int numchars = 1; char buf[1024]; size_t bytes_read; long file_size; // 丢弃请求头 buf[0] = 'A'; buf[1] = '\0'; while ((numchars > 0) && strcmp("\n", buf)) numchars = get_line(client, buf, sizeof(buf)); // 使用二进制模式打开文件 resource = fopen(filename, "rb"); if (resource == NULL) { not_found(client); return; } // 获取文件大小 fseek(resource, 0, SEEK_END); file_size = ftell(resource); fseek(resource, 0, SEEK_SET); // 发送HTTP头 const char *content_type = get_mime_type(filename); // 创建并发送头部 char header_buf[2048]; sprintf(header_buf, "HTTP/1.0 200 OK\r\n"); send(client, header_buf, strlen(header_buf), 0); sprintf(header_buf, SERVER_STRING); send(client, header_buf, strlen(header_buf), 0); sprintf(header_buf, "Content-Type: %s\r\n", content_type); send(client, header_buf, strlen(header_buf), 0); sprintf(header_buf, "Content-Length: %ld\r\n", file_size); send(client, header_buf, strlen(header_buf), 0); sprintf(header_buf, "\r\n"); send(client, header_buf, strlen(header_buf), 0); // 使用二进制模式发送文件内容 while ((bytes_read = fread(buf, 1, sizeof(buf), resource)) > 0) { ssize_t sent = send(client, buf, bytes_read, MSG_NOSIGNAL); if (sent < 0) { // 处理发送错误(如连接关闭) break; } } fclose(resource); } /**********************************************************************/ /* 启动服务器 */ /**********************************************************************/ int startup(unsigned short *port) { int httpd = 0; struct sockaddr_in name; /* 创建socket */ httpd = socket(PF_INET, SOCK_STREAM, 0); if (httpd == -1) error_die("socket"); memset(&name, 0, sizeof(name)); name.sin_family = AF_INET; name.sin_port = htons(*port); name.sin_addr.s_addr = htonl(INADDR_ANY); /* 绑定地址 */ if (bind(httpd, (struct sockaddr *)&name, sizeof(name)) < 0) error_die("bind"); /* 若预设端口为0,随机取用可用端口*/ if (*port == 0) { socklen_t namelen = sizeof(name); if (getsockname(httpd, (struct sockaddr *)&name, &namelen) == -1) error_die("getsockname"); *port = ntohs(name.sin_port); } /* 监听连接 */ if (listen(httpd, 5) < 0) error_die("listen"); return(httpd); } /**********************************************************************/ /* 501 Not Implemented */ /**********************************************************************/ void unimplemented(int client) { char buf[1024]; sprintf(buf, "HTTP/1.0 501 Method Not Implemented\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, SERVER_STRING); send(client, buf, strlen(buf), 0); sprintf(buf, "Content-Type: text/html\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, "\r\n"); send(client, buf, strlen(buf), 0); sprintf(buf, "<html><body><h1>501 Not Implemented</h1><p>The requested method is not implemented.</p></body></html>\r\n"); send(client, buf, strlen(buf), 0); } // 设置套接字发送超时(在主循环accept后调用) void set_socket_timeout(int sockfd, int timeout_sec) { struct timeval tv; tv.tv_sec = timeout_sec; // 超时秒数 tv.tv_usec = 0; if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) { perror("setsockopt SO_SNDTIMEO failed"); } } /**********************************************************************/ /* 主函数(多进程实现)*/ /**********************************************************************/ int main(void) { int server_sock = -1; unsigned short port = 8080; int client_sock = -1; struct sockaddr_in client_name; socklen_t client_name_len = sizeof(client_name); pid_t pid; // 设置SIGCHLD处理函数避免僵尸进程 struct sigaction sa; sa.sa_handler = SIG_IGN; // 忽略SIGCHLD信号,自动回收子进程 sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("sigaction"); exit(EXIT_FAILURE); } server_sock = startup(&port); printf("HTTP server running on port %d\n", port); signal(SIGPIPE, SIG_IGN); // 忽略SIGPIPE信号 while (1) { /* 接受连接 */ client_sock = accept(server_sock, (struct sockaddr *)&client_name, &client_name_len); if (client_sock == -1) { perror("accept"); continue; } /* 创建子进程处理请求 */ pid = fork(); if (pid < 0) { perror("fork"); close(client_sock); } else if (pid == 0) { // 子进程 close(server_sock); // 关闭监听套接字(子进程不需要) // 动态分配内存传递socket描述符 int *pclient = malloc(sizeof(int)); if (!pclient) { perror("malloc failed"); close(client_sock); exit(EXIT_FAILURE); } *pclient = client_sock; accept_request(pclient); // 处理请求 exit(EXIT_SUCCESS); // 子进程退出 } else { // 父进程 close(client_sock); // 关闭客户端套接字(父进程不需要) } } close(server_sock); return 0; } 用windows浏览器向该webserver发送POST请求时报错net::ERR_CONNECTION_RESET,而Linux浏览器正常,试分析原因
08-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值