127 lines
3.2 KiB
C
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;
|
|
}
|