vessel/lab/keepalive.c
2025-06-13 17:58:13 +03:00

127 lines
3.2 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <sys/time.h>
#include <arpa/inet.h>
#ifndef NULL
# define NULL ((void *)0)
#endif /* NULL */
#define PORT 8080
#define BUFFER_SIZE 1024
static int server_socket;
static int sock_true = 1;
static void handle_conn(int client_socket, char *buffer) {
char method[16], path[256];
sscanf(buffer, "%s %s", method, path);
char response[BUFFER_SIZE] = { 0 };
printf("Connection %d: %s %s\n", client_socket, method, path);
if (0 == strcmp(path, "/")) {
sprintf(response,
"HTTP/1.1 200 OK\r\n"
"Connection: keep-alive\r\n"
"Content-Length: 29\r\n"
"Content-Type: text/html\r\n\r\n"
"<h1>Works!</h1> <img src=x />");
} else {
sprintf(response,
"HTTP/1.1 404 Not Found\r\n"
"Connection: keep-alive\r\n"
"Content-Length: 13\r\n"
"Content-Type: text/plain\r\n\r\n"
"404 Not Found");
}
send(client_socket, response, strlen(response), 0);
}
static void *handle_client(void *arg) {
int client_socket = *(int *)arg;
free(arg);
char buffer[BUFFER_SIZE];
printf("Handling connection %d...\n", client_socket);
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout));
while (1) {
memset(buffer, 0, sizeof(buffer));
if (recv(client_socket, buffer, sizeof(buffer) - 1, 0) <= 0) {
printf("Closing connection %d...\n", client_socket);
break;
}
handle_conn(client_socket, buffer);
}
shutdown(client_socket, SHUT_RDWR);
close(client_socket);
return NULL;
}
static void close_server(int sig) {
printf("\nHandling signal %d\n", sig);
shutdown(server_socket, SHUT_RDWR);
close(server_socket);
exit(0);
}
int main(void) {
server_socket = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &sock_true, sizeof(sock_true));
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
server_address.sin_port = htons(PORT);
bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address));
listen(server_socket, SOMAXCONN);
signal(SIGINT, close_server);
printf("Server listening on 127.0.0.1:%d ...\n", PORT);
while (1) {
int *client_socket = malloc(sizeof(int));
*client_socket = accept(server_socket, NULL, NULL);
if (*client_socket < 0) {
perror("Accept failed");
free(client_socket);
continue;
}
pthread_t thread_id;
if (pthread_create(&thread_id, NULL, handle_client, client_socket) != 0) {
perror("Failed to create thread");
close(*client_socket);
free(client_socket);
} else {
pthread_detach(thread_id);
}
}
shutdown(server_socket, SHUT_RDWR);
close(server_socket);
return 0;
}