Skip to content

Instantly share code, notes, and snippets.

@shonenada
Created April 20, 2013 04:55
Show Gist options
  • Save shonenada/5424807 to your computer and use it in GitHub Desktop.
Save shonenada/5424807 to your computer and use it in GitHub Desktop.
A simple http server in C
#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 <fcntl.h>
#define WEBROOT "./webroot" // the web server's root directory
#define PORT = 8080;
void handle_connection(int, struct sockaddr_in*);
int get_file_size(int);
int main()
{
int sockfd, clientfd;
socklen_t cliaddr_len;
struct sockaddr_in server_addr, client_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
{
printf("Error!");
exit(1);
}
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int br = bind(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr));
if(br == -1)
{
printf("Error!");
exit(1);
}
if((listen(sockfd, 20)) == -1)
{
printf("Error");
exit(1);
}
while(1)
{
clientfd = accept(sockfd, (struct sockaddr *) &client_addr, &cliaddr_len);
if(clientfd == -1)
{
printf("waiting for connection.");
}
handle_connection(clientfd, &client_addr);
}
return 1;
}
void handle_connection(int sockfd, struct sockaddr_in *client_addr_ptr)
{
unsigned char *ptr, request[500], resource[500];
int fd, length;
length = recv(sockfd, request, 500, 0);
printf("Got request from %s:%d \"%s\"\n", inet_ntoa(client_addr_ptr->sin_addr), ntohs(client_addr_ptr->sin_port), 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(strncmp(request, "HEAD ", 5) == 0)
ptr = request + 5;
if(ptr == NULL) {
printf("\tUNKNOWN REQUEST!\n");
} else {
if (ptr[strlen(ptr) - 1] == '/')
strcat(ptr, "index.html");
strcpy(resource, WEBROOT);
strcat(resource, ptr);
fd = open(resource, O_RDONLY, 0);
printf("\tOpening \'%s\'\t", resource);
if(fd == -1) {
printf(" 404 Not Found\n");
send(sockfd, "HTTP/1.0 404 NOT FOUND\r\n", 24, 0);
} else {
printf(" 200 OK\n");
send(sockfd, "HTTP/1.0 200 OK\r\n", 17, 0);
send(sockfd, "Server: C\r\n\r\n", 13, 0);
if(ptr == request + 4) {
if( (length = get_file_size(fd)) == -1)
{
printf("getting resource file size");
exit(1);
}
if( (ptr = (unsigned char *) malloc(length)) == NULL)
{
printf("allocating memory for reading resource");
exit(1);
}
read(fd, ptr, length);
send(sockfd, ptr, length, 0)
free(ptr);
}
close(fd);
}
}
}
shutdown(sockfd, SHUT_RDWR);
}
int get_file_size(int fd) {
struct stat stat_struct;
if(fstat(fd, &stat_struct) == -1)
return -1;
return (int) stat_struct.st_size;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment