纯C语言实现的一个简单的web服务器
发布时间:2020-12-16 07:44:04 所属栏目:百科 来源:网络整理
导读:今天PHP站长网 52php.cn把收集自互联网的代码分享给大家,仅供参考。 /* * WebServer.c * * Created on: Nov 3,2012 * Author: pavithra * * A web server in C language using only the standard libraries. * The port
以下代码由PHP站长网 52php.cn收集自互联网 现在PHP站长网小编把它分享给大家,仅供参考 /* * WebServer.c * * Created on: Nov 3,2012 * Author: pavithra * * A web server in C language using only the standard libraries. * The port number is passed as an argument. * */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <fcntl.h> #include <errno.h> #define EOL "rn" #define EOL_SIZE 2 typedef struct { char *ext; char *mediatype; } extn; //Possible media types extn extensions[] ={ {"gif","image/gif" },{"txt","text/plain" },{"jpg","image/jpg" },{"jpeg","image/jpeg"},{"png","image/png" },{"ico","image/ico" },{"zip","image/zip" },{"gz","image/gz" },{"tar","image/tar" },{"htm","text/html" },{"html",{"php",{"pdf","application/pdf"},"application/octet-stream"},{"rar",{0,0} }; /* A helper function */ void error(const char *msg) { perror(msg); exit(1); } /* A helper function */ int get_file_size(int fd) { struct stat stat_struct; if (fstat(fd,&stat_struct) == -1) return (1); return (int) stat_struct.st_size; } /* A helper function */ void send_new(int fd,char *msg) { int len = strlen(msg); if (send(fd,msg,len,0) == -1) { printf("Error in sendn"); } } /* This function recieves the buffer until an "End of line(EOL)" byte is recieved */ int recv_new(int fd,char *buffer) { char *p = buffer; // Use of a pointer to the buffer rather than dealing with the buffer directly int eol_matched = 0; // Use to check whether the recieved byte is matched with the buffer byte or not while (recv(fd,p,1,0) != 0) // Start receiving 1 byte at a time { if (*p == EOL[eol_matched]) // if the byte matches with the first eol byte that is 'r' { ++eol_matched; if (eol_matched == EOL_SIZE) // if both the bytes matches with the EOL { *(p + 1 - EOL_SIZE) = ' '; // End the string return (strlen(buffer)); // Return the bytes recieved } } else { eol_matched = 0; } p++; // Increment the pointer to receive next byte } return (0); } /* A helper function: Returns the web root location. */ char* webroot() { // open the file "conf" for reading FILE *in = fopen("conf","rt"); // read the first line from the file char buff[1000]; fgets(buff,1000,in); // close the stream fclose(in); char* nl_ptr = strrchr(buff,'n'); if (nl_ptr != NULL) *nl_ptr = ' '; return strdup(buff); } /* Handles php requests */ void php_cgi(char* script_path,int fd) { send_new(fd,"HTTP/1.1 200 OKn Server: Web Server in Cn Connection: closen"); dup2(fd,STDOUT_FILENO); char script[500]; strcpy(script,"SCRIPT_FILENAME="); strcat(script,script_path); putenv("GATEWAY_INTERFACE=CGI/1.1"); putenv(script); putenv("QUERY_STRING="); putenv("REQUEST_METHOD=GET"); putenv("REDIRECT_STATUS=true"); putenv("SERVER_PROTOCOL=HTTP/1.1"); putenv("REMOTE_HOST=127.0.0.1"); execl("/usr/bin/php-cgi","php-cgi",NULL); } /* This function parses the HTTP requests,arrange resource locations,check for supported media types,serves files in a web root,sends the HTTP error codes. */ int connection(int fd) { char request[500],resource[500],*ptr; int fd1,length; if (recv_new(fd,request) == 0) { printf("Recieve Failedn"); } printf("%sn",request); // Check for a valid browser request ptr = strstr(request," HTTP/"); if (ptr == NULL) { printf("NOT HTTP !n"); } else { *ptr = 0; ptr = NULL; if (strncmp(request,"GET ",4) == 0) { ptr = request + 4; } if (ptr == NULL) { printf("Unknown Request ! n"); } else { if (ptr[strlen(ptr) - 1] == '/') { strcat(ptr,"index.html"); } strcpy(resource,webroot()); strcat(resource,ptr); char* s = strchr(ptr,'.'); int i; for (i = 0; extensions[i].ext != NULL; i++) { if (strcmp(s + 1,extensions[i].ext) == 0) { fd1 = open(resource,O_RDONLY,0); printf("Opening "%s"n",resource); if (fd1 == -1) { printf("404 File not found Errorn"); send_new(fd,"HTTP/1.1 404 Not Foundrn"); send_new(fd,"Server : Web Server in Crnrn"); send_new(fd,"<html><head><title>404 Not Found</head></title>"); send_new(fd,"<body><p>404 Not Found: The requested resource could not be found!</p></body></html>"); //Handling php requests } else if (strcmp(extensions[i].ext,"php") == 0) { php_cgi(resource,fd); sleep(1); close(fd); exit(1); } else { printf("200 OK,Content-Type: %snn",extensions[i].mediatype); send_new(fd,"HTTP/1.1 200 OKrn"); send_new(fd,"Server : Web Server in Crnrn"); if (ptr == request + 4) // if it is a GET request { if ((length = get_file_size(fd1)) == -1) printf("Error in getting size !n"); size_t total_bytes_sent = 0; ssize_t bytes_sent; while (total_bytes_sent < length) { //Zero copy optimization if ((bytes_sent = sendfile(fd,fd1,length - total_bytes_sent)) <= 0) { if (errno == EINTR || errno == EAGAIN) { continue; } perror("sendfile"); return -1; } total_bytes_sent += bytes_sent; } } } break; } int size = sizeof(extensions) / sizeof(extensions[0]); if (i == size - 2) { printf("415 Unsupported Media Typen"); send_new(fd,"HTTP/1.1 415 Unsupported Media Typern"); send_new(fd,"Server : Web Server in Crnrn"); send_new(fd,"<html><head><title>415 Unsupported Media Type</head></title>"); send_new(fd,"<body><p>415 Unsupported Media Type!</p></body></html>"); } } close(fd); } } shutdown(fd,SHUT_RDWR); } int main(int argc,char *argv[]) { int sockfd,newsockfd,portno,pid; socklen_t clilen; struct sockaddr_in serv_addr,cli_addr; if (argc < 2) { fprintf(stderr,"ERROR,no port providedn"); exit(1); } sockfd = socket(AF_INET,SOCK_STREAM,0); if (sockfd < 0) error("ERROR opening socket"); bzero((char *) &serv_addr,sizeof(serv_addr)); portno = atoi(argv[1]); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(portno); if (bind(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) error("ERROR on binding"); listen(sockfd,5); clilen = sizeof(cli_addr); /* Server runs forever,forking off a separate process for each connection. */ while (1) { newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr,&clilen); if (newsockfd < 0) error("ERROR on accept"); pid = fork(); if (pid < 0) error("ERROR on fork"); if (pid == 0) { close(sockfd); connection(newsockfd); exit(0); } else close(newsockfd); } /* end of while */ close(sockfd); return 0; /* we never get here */ } 以上内容由PHP站长网【52php.cn】收集整理供大家参考研究 如果以上内容对您有帮助,欢迎收藏、点赞、推荐、分享。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |