Created
February 23, 2024 07:15
-
-
Save i-rebel-aj/c2eb2e3013f1d3fe0b69ee22aa337269 to your computer and use it in GitHub Desktop.
A simple single threaded webserver written in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<stdio.h> | |
#include<stdlib.h> | |
#include <string.h> | |
#include<unistd.h> | |
#include<sys/socket.h> | |
#include<signal.h> | |
#include <netinet/in.h> | |
//Maximum Application Buffer | |
/** | |
Max Amount of memory from network (Request Size) | |
*/ | |
#define APP_MAX_BUFFER 1024 | |
#define PORT 3001 | |
#define MAX_BACKLOG_QUEUE_SIZE 10 | |
#define SUCCESS_RESPONSE "HTTP/1.1 200 OK\r\nContent-Length: 12\r\nContent-Type: text/plain\r\n\r\nHello World\n" | |
/** | |
Single Threaded HTTP Webserver | |
*/ | |
void send_response(int server_fd){ | |
struct sockaddr_in client_address; | |
int clinet_address_len=sizeof(client_address); | |
int client_fd=accept(server_fd, (struct sockaddr *)&client_address, (socklen_t *)&clinet_address_len); | |
if(client_fd==-1){ | |
perror("Accept Failed"); | |
exit(EXIT_FAILURE); | |
} | |
char buffer[APP_MAX_BUFFER]={0}; | |
if(read(client_fd, buffer, APP_MAX_BUFFER)==-1){ | |
perror("Request can not read to buffer\n"); | |
} | |
printf("The request is:\n%s\n", buffer); | |
write(client_fd, SUCCESS_RESPONSE, strlen(SUCCESS_RESPONSE)); | |
close(client_fd); | |
} | |
int main(){ | |
//Define socket address | |
struct sockaddr_in server_address; | |
int server_fd=socket(AF_INET, SOCK_STREAM, 0); | |
if(server_fd==-1){ | |
perror("Socket Failed"); | |
exit(EXIT_FAILURE); | |
} | |
/** | |
Make Socket Reusable Even if server is closed | |
*/ | |
int opt = 1; | |
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { | |
perror("setsockopt"); | |
exit(EXIT_FAILURE); | |
} | |
server_address.sin_family=AF_INET; //ipv4 | |
server_address.sin_port= htons(PORT) ; | |
server_address.sin_addr.s_addr= INADDR_ANY; //Listening 0.0.0.0 inefraces | |
if(bind(server_fd, (struct sockaddr *)&server_address, sizeof(server_address))<0){ | |
perror("Bind Failed"); | |
exit(EXIT_FAILURE); | |
} | |
//Creates the Queue | |
//Listen for clients, with 10 backlog (10 connections in accept queue) | |
if(listen(server_fd,MAX_BACKLOG_QUEUE_SIZE )){ | |
perror("Listen Failed"); | |
exit(EXIT_FAILURE); | |
} | |
printf("Server running, press Ctrl+C to exit...\n"); | |
while(1){ | |
printf("Waiting for connection\n"); | |
send_response(server_fd); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment