加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

纯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】收集整理供大家参考研究

如果以上内容对您有帮助,欢迎收藏、点赞、推荐、分享。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读