Created
December 28, 2022 02:03
-
-
Save marcusziade/76a2fe88fec9c5c26d63b453709b8c89 to your computer and use it in GitHub Desktop.
websever in C by skynet
This file contains hidden or 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 <pthread.h> | |
#include <unistd.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#define BUFFER_SIZE 1024 | |
#define NUM_THREADS 5 | |
// Structure for passing arguments to the thread function | |
typedef struct { | |
int client_fd; | |
struct sockaddr_in client_addr; | |
} thread_arg_t; | |
// The thread function that handles a client request | |
void* handle_request(void* arg) { | |
thread_arg_t* thread_arg = (thread_arg_t*)arg; | |
int client_fd = thread_arg->client_fd; | |
struct sockaddr_in client_addr = thread_arg->client_addr; | |
free(arg); | |
char buffer[BUFFER_SIZE]; | |
int bytes_received = recv(client_fd, buffer, BUFFER_SIZE, 0); | |
if (bytes_received < 0) { | |
perror("recv"); | |
return NULL; | |
} | |
printf("Received %d bytes from %s:%d\n", bytes_received, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); | |
// Send a simple response to the client | |
const char* response = "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 12\n\nHello, World!\n"; | |
send(client_fd, response, strlen(response), 0); | |
close(client_fd); | |
return NULL; | |
} | |
int main(int argc, char** argv) { | |
if (argc < 2) { | |
fprintf(stderr, "Usage: %s [port]\n", argv[0]); | |
return 1; | |
} | |
// Create the server socket | |
int server_fd = socket(AF_INET, SOCK_STREAM, 0); | |
if (server_fd < 0) { | |
perror("socket"); | |
return 1; | |
} | |
// Bind the socket to the specified port | |
int port = atoi(argv[1]); | |
struct sockaddr_in server_addr; | |
memset(&server_addr, 0, sizeof(server_addr)); | |
server_addr.sin_family = AF_INET; | |
server_addr.sin_addr.s_addr = INADDR_ANY; | |
server_addr.sin_port = htons(port); | |
if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { | |
perror("bind"); | |
return 1; | |
} | |
// Listen for incoming connections | |
if (listen(server_fd, 5) < 0) | |
{ | |
perror("listen"); | |
return 1; | |
} | |
printf("Listening on port %d\n", port); | |
// Create a pool of threads to handle client requests | |
pthread_t threads[NUM_THREADS]; | |
for (int i = 0; i < NUM_THREADS; i++) { | |
if (pthread_create(&threads[i], NULL, handle_request, NULL) != 0) { | |
perror("pthread_create"); | |
return 1; | |
} | |
} | |
// Accept client connections and dispatch them to the threads | |
while (1) { | |
struct sockaddr_in client_addr; | |
socklen_t client_addr_len = sizeof(client_addr); | |
int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_addr_len); | |
if (client_fd < 0) { | |
perror("accept"); | |
return 1; | |
} | |
// Find an available thread to handle the request | |
int i; | |
for (i = 0; i < NUM_THREADS; i++) { | |
if (pthread_tryjoin_np(threads[i], NULL) == 0) { | |
break; | |
} | |
} | |
// If no threads are available, close the connection | |
if (i == NUM_THREADS) { | |
printf("No threads available, closing connection\n"); | |
close(client_fd); | |
continue; | |
} | |
// Pass the client connection to the thread | |
thread_arg_t* thread_arg = (thread_arg_t*)malloc(sizeof(thread_arg_t)); | |
thread_arg->client_fd = client_fd; | |
thread_arg->client_addr = client_addr; | |
if (pthread_create(&threads[i], NULL, handle_request, thread_arg) != 0) { | |
perror("pthread_create"); | |
return 1; | |
} | |
} | |
return 0; | |
} | |
/* | |
This code creates a fixed pool of threads, and each time a new connection is accepted it tries to find an available thread to handle the request. If no threads are available, the connection is closed. | |
I hope this helps! Let me know if you have any questions or need further clarification. | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment