webserver.c Simple HTTP server sample for sanos
2016-04-01 14:30
453 查看
// // webserver.c // // Simple HTTP server sample for sanos // #include <os.h> #include <stdio.h> #include <string.h> #include <time.h> #include <sys/stat.h> #include <dirent.h> #define SERVER "webserver/1.0" #define PROTOCOL "HTTP/1.0" #define RFC1123FMT "%a, %d %b %Y %H:%M:%S GMT" #define PORT 80 char *get_mime_type(char *name) { char *ext = strrchr(name, '.'); if (!ext) return NULL; if (strcmp(ext, ".html") == 0 || strcmp(ext, ".htm") == 0) return "text/html"; if (strcmp(ext, ".jpg") == 0 || strcmp(ext, ".jpeg") == 0) return "image/jpeg"; if (strcmp(ext, ".gif") == 0) return "image/gif"; if (strcmp(ext, ".png") == 0) return "image/png"; if (strcmp(ext, ".css") == 0) return "text/css"; if (strcmp(ext, ".au") == 0) return "audio/basic"; if (strcmp(ext, ".wav") == 0) return "audio/wav"; if (strcmp(ext, ".avi") == 0) return "video/x-msvideo"; if (strcmp(ext, ".mpeg") == 0 || strcmp(ext, ".mpg") == 0) return "video/mpeg"; if (strcmp(ext, ".mp3") == 0) return "audio/mpeg"; return NULL; } void send_headers(FILE *f, int status, char *title, char *extra, char *mime, int length, time_t date) { time_t now; char timebuf[128]; fprintf(f, "%s %d %s\r\n", PROTOCOL, status, title); fprintf(f, "Server: %s\r\n", SERVER); now = time(NULL); strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now)); fprintf(f, "Date: %s\r\n", timebuf); if (extra) fprintf(f, "%s\r\n", extra); if (mime) fprintf(f, "Content-Type: %s\r\n", mime); if (length >= 0) fprintf(f, "Content-Length: %d\r\n", length); if (date != -1) { strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&date)); fprintf(f, "Last-Modified: %s\r\n", timebuf); } fprintf(f, "Connection: close\r\n"); fprintf(f, "\r\n"); } void send_error(FILE *f, int status, char *title, char *extra, char *text) { send_headers(f, status, title, extra, "text/html", -1, -1); fprintf(f, "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\r\n", status, title); fprintf(f, "<BODY><H4>%d %s</H4>\r\n", status, title); fprintf(f, "%s\r\n", text); fprintf(f, "</BODY></HTML>\r\n"); } void send_file(FILE *f, char *path, struct stat *statbuf) { char data[4096]; int n; FILE *file = fopen(path, "r"); if (!file) send_error(f, 403, "Forbidden", NULL, "Access denied."); else { int length = S_ISREG(statbuf->st_mode) ? statbuf->st_size : -1; send_headers(f, 200, "OK", NULL, get_mime_type(path), length, statbuf->st_mtime); while ((n = fread(data, 1, sizeof(data), file)) > 0) fwrite(data, 1, n, f); fclose(file); } } int process(FILE *f) { char buf[4096]; char *method; char *path; char *protocol; struct stat statbuf; char pathbuf[4096]; int len; if (!fgets(buf, sizeof(buf), f)) return -1; printf("URL: %s", buf); method = strtok(buf, " "); path = strtok(NULL, " "); protocol = strtok(NULL, "\r"); if (!method || !path || !protocol) return -1; fseek(f, 0, SEEK_CUR); // Force change of stream direction if (stricmp(method, "GET") != 0) send_error(f, 501, "Not supported", NULL, "Method is not supported."); else if (stat(path, &statbuf) < 0) send_error(f, 404, "Not Found", NULL, "File not found."); else if (S_ISDIR(statbuf.st_mode)) { len = strlen(path); if (len == 0 || path[len - 1] != '/') { snprintf(pathbuf, sizeof(pathbuf), "Location: %s/", path); send_error(f, 302, "Found", pathbuf, "Directories must end with a slash."); } else { snprintf(pathbuf, sizeof(pathbuf), "%sindex.html", path); if (stat(pathbuf, &statbuf) >= 0) send_file(f, pathbuf, &statbuf); else { DIR *dir; struct dirent *de; send_headers(f, 200, "OK", NULL, "text/html", -1, statbuf.st_mtime); fprintf(f, "<HTML><HEAD><TITLE>Index of %s</TITLE></HEAD>\r\n<BODY>", path); fprintf(f, "<H4>Index of %s</H4>\r\n<PRE>\n", path); fprintf(f, "Name Last Modified Size\r\n"); fprintf(f, "<HR>\r\n"); if (len > 1) fprintf(f, "<A HREF=\"..\">..</A>\r\n"); dir = opendir(path); while ((de = readdir(dir)) != NULL) { char timebuf[32]; struct tm *tm; strcpy(pathbuf, path); strcat(pathbuf, de->d_name); stat(pathbuf, &statbuf); tm = gmtime(&statbuf.st_mtime); strftime(timebuf, sizeof(timebuf), "%d-%b-%Y %H:%M:%S", tm); fprintf(f, "<A HREF=\"%s%s\">", de->d_name, S_ISDIR(statbuf.st_mode) ? "/" : ""); fprintf(f, "%s%s", de->d_name, S_ISDIR(statbuf.st_mode) ? "/</A>" : "</A> "); if (de->d_namlen < 32) fprintf(f, "%*s", 32 - de->d_namlen, ""); if (S_ISDIR(statbuf.st_mode)) fprintf(f, "%s\r\n", timebuf); else fprintf(f, "%s %10d\r\n", timebuf, statbuf.st_size); } closedir(dir); fprintf(f, "</PRE>\r\n<HR>\r\n<ADDRESS>%s</ADDRESS>\r\n</BODY></HTML>\r\n", SERVER); } } } else send_file(f, path, &statbuf); return 0; } int main(int argc, char *argv[]) { int sock; struct sockaddr_in sin; sock = socket(AF_INET, SOCK_STREAM, 0); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(PORT); bind(sock, (struct sockaddr *) &sin, sizeof(sin)); listen(sock, 5); printf("HTTP server listening on port %d at %s\n", PORT, inet_ntoa(peb->ipaddr)); while (1) { int s; FILE *f; s = accept(sock, NULL, NULL); if (s < 0) break; f = fdopen(s, "r+"); process(f); fclose(f); } close(sock); return 0; }
相关文章推荐
- HTTPS 流程详解
- 第三章 改进神经网络的学习方式(中下)
- 第三章 改进神经网络的学习方式(上)
- 5.七个重点网络协议
- HTTP 错误 500.22 - Internal Server Error
- 第三章 改进神经网络的学习方式(上中)
- Neural Networks神经网络编程入门
- 配置tomcat https的步骤
- http消息头设置
- 牛津大学视觉几何组VGG卷积神经网络实践教程VGG Convolutional Neural Networks Practical
- linux编程获取本机网络相关参数
- 写给后端程序员的HTTP缓存原理介绍
- iOS网络缓存扫盲篇
- HTTPSQS 、gearman研究
- 后端知识体系--一次完整的HTTP请求
- springMVC + hadoop + httpclient 文件上传请求直接写入hdfs
- HTTP请求
- 卸载 linux http
- 网络受限下,使用Nexus要解决的两个问题
- 浅析android下如何通过jni监控wifi网络连接、dhcpcd执行和power电源控制