Skip to content

Instantly share code, notes, and snippets.

@marcusziade
Created December 28, 2022 02:03
Show Gist options
  • Save marcusziade/76a2fe88fec9c5c26d63b453709b8c89 to your computer and use it in GitHub Desktop.
Save marcusziade/76a2fe88fec9c5c26d63b453709b8c89 to your computer and use it in GitHub Desktop.
websever in C by skynet
#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