标准c语言建立简单的web服务器,纯C语言实现的一个简单的web服务器

/*

* 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

#include

#include

#include

#include

#include

#include

#include

#include

#define EOL "\r\n"

#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","text/html" },

{"php", "text/html" },

{"pdf","application/pdf"},

{"zip","application/octet-stream"},

{"rar","application/octet-stream"},

{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 send\n");

}

}

/*

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) = '\0'; // 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 = '\0';

return strdup(buff);

}

/*

Handles php requests

*/

void php_cgi(char* script_path, int fd) {

send_new(fd, "HTTP/1.1 200 OK\n Server: Web Server in C\n Connection: close\n");

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 Failed\n");

}

printf("%s\n", 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 Error\n");

send_new(fd, "HTTP/1.1 404 Not Found\r\n");

send_new(fd, "Server : Web Server in C\r\n\r\n");

send_new(fd, "

404 Not Found");

send_new(fd, "

404 Not Found: The requested resource could not be found!

");

//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: %s\n\n",

extensions[i].mediatype);

send_new(fd, "HTTP/1.1 200 OK\r\n");

send_new(fd, "Server : Web Server in C\r\n\r\n");

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, 0,

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 Type\n");

send_new(fd, "HTTP/1.1 415 Unsupported Media Type\r\n");

send_new(fd, "Server : Web Server in C\r\n\r\n");

send_new(fd, "

415 Unsupported Media Type");

send_new(fd, "

415 Unsupported Media Type!

");

}

}

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 provided\n");

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 */

}

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com

特别注意:本站所有转载文章言论不代表本站观点!

本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值