From fec3f555e9eda9fd8aab9161fe3eb1d47ee68118 Mon Sep 17 00:00:00 2001 From: Ajurna Date: Mon, 28 Jul 2025 17:31:05 +0100 Subject: [PATCH] Refactored project structure, added multithreaded echo server and prime checking server, updated tests. --- .idea/cprotohackers.iml | 8 +- .idea/misc.xml | 3 + CMakeLists.txt | 22 ++++- data.c | 58 ++++++++++++- data.h | 8 +- echo_server_test.py | 55 ++++++++++++ main.c | 79 ----------------- main.h | 21 ----- parallel_echo_client_test.py | 84 ++++++++++++++++++ prime_time_server_tests.py | 163 +++++++++++++++++++++++++++++++++++ server00.c | 68 +++++++++++++++ server00.h | 17 ++++ server01.c | 124 ++++++++++++++++++++++++++ server01.h | 21 +++++ 14 files changed, 621 insertions(+), 110 deletions(-) create mode 100644 echo_server_test.py delete mode 100644 main.c delete mode 100644 main.h create mode 100644 parallel_echo_client_test.py create mode 100644 prime_time_server_tests.py create mode 100644 server00.c create mode 100644 server00.h create mode 100644 server01.c create mode 100644 server01.h diff --git a/.idea/cprotohackers.iml b/.idea/cprotohackers.iml index f08604b..83f477b 100644 --- a/.idea/cprotohackers.iml +++ b/.idea/cprotohackers.iml @@ -1,2 +1,8 @@ - \ No newline at end of file + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 0b76fe5..a424e87 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,8 @@ + + diff --git a/CMakeLists.txt b/CMakeLists.txt index 072582b..980bd4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,24 @@ cmake_minimum_required(VERSION 3.31) -project(cprotohackers C) +project(server00 C) set(CMAKE_C_STANDARD 23) -add_executable(cprotohackers main.c - main.h + +set(COMMON_SOURCES data.c data.h) -target_link_libraries(cprotohackers wsock32 ws2_32) + + +add_executable(server00 server00.c + server00.h + ${COMMON_SOURCES}) +target_link_libraries(server00 wsock32 ws2_32) + +find_package(json-c CONFIG REQUIRED) + + +add_executable(server01 server01.c + server01.h + ${COMMON_SOURCES}) + +target_link_libraries(server01 PRIVATE wsock32 ws2_32 json-c::json-c) \ No newline at end of file diff --git a/data.c b/data.c index 99af864..5e6caae 100644 --- a/data.c +++ b/data.c @@ -6,6 +6,25 @@ #include #include +#define PORT 40000 +SOCKET get_listen_socket() { + WSADATA WSAData; + + SOCKET client; + + SOCKADDR_IN serverAddr, clientAddr; + + WSAStartup(MAKEWORD(2,0), &WSAData); + SOCKET server = socket(AF_INET, SOCK_STREAM, 0); + + serverAddr.sin_addr.s_addr = INADDR_ANY; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(PORT); + + bind(server, (SOCKADDR *)&serverAddr, sizeof(serverAddr)); + listen(server, 0); + return server; +} char_array_t *char_array_create(int capacity) { char_array_t *array = malloc(sizeof(char_array_t)); @@ -22,10 +41,11 @@ void char_array_append(char_array_t *array, char *value, size_t length) { if (array->data == NULL) { exit(1); } - printf("old size: %llu\n", array->size); - printf("length: %llu\n", length); + // char *temp = calloc(length+1, sizeof(char)); + // memcpy(temp, value, length); + // printf("Appending '%s' bytes\n", temp); + // free(temp); size_t new_size = array->size + length; - printf("New size: %llu\n", new_size); if (new_size > array->capacity) { array->capacity = new_size; char *new_array = realloc(array->data, array->capacity); @@ -47,3 +67,35 @@ void char_array_wipe(char_array_t *array) { array->size = 0; memset(array->data, 0, array->capacity); }; + +bool char_array_has_char(char_array_t *array, char c) { + const char *ret = memchr(array->data, c, array->size); + if (ret == NULL) { + return false; + } + return true; +}; +char *char_array_get_until_char(char_array_t *array, char c) { + size_t idx = 0; + for (size_t i = 0; i < array->size; i++) { + if (array->data[i] == c) { + idx = i; + break; + } + } + if (idx == 0) { + return NULL; + } + char *ret = malloc(idx+1); + memcpy(ret, array->data, idx); + ret[idx] = '\0'; + char *temp = calloc(array->capacity, sizeof(char)); + size_t new_i = 0; + for (size_t i = idx+1; i < array->size; i++) { + temp[new_i++] = array->data[i]; + } + free(array->data); + array->data = temp; + array->size = new_i; + return ret; +}; \ No newline at end of file diff --git a/data.h b/data.h index d488001..e005199 100644 --- a/data.h +++ b/data.h @@ -1,6 +1,6 @@ #pragma once #include - +#include typedef struct CharArray { size_t size; size_t capacity; @@ -11,4 +11,8 @@ char_array_t *char_array_create(int size); void char_array_destroy(char_array_t *array); void char_array_append(char_array_t *array, char *value, size_t length); void char_array_print(const char_array_t *array); -void char_array_wipe(char_array_t *array); \ No newline at end of file +void char_array_wipe(char_array_t *array); +bool char_array_has_char(char_array_t *array, char c); +char *char_array_get_until_char(char_array_t *array, char c); + +SOCKET get_listen_socket(); \ No newline at end of file diff --git a/echo_server_test.py b/echo_server_test.py new file mode 100644 index 0000000..a0eee28 --- /dev/null +++ b/echo_server_test.py @@ -0,0 +1,55 @@ +import socket +import time + +def test_echo_server(host='localhost', port=40000, message="Hello, Echo Server!"): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + try: + s.connect((host, port)) + print(f"Connected to {host}:{port}") + + # Send the message + print(f"Sending message of length: {len(message)}") + s.sendall(message.encode()) + s.shutdown(socket.SHUT_WR) + + + # Receive the response in chunks + chunks = [] + bytes_received = 0 + while bytes_received < len(message): + chunk = s.recv(1024) + if not chunk: + break + chunks.append(chunk) + bytes_received += len(chunk) + time.sleep(0.1) # Match the server's Sleep(100) + + response = b''.join(chunks).decode() + print(f"Received {len(response)} bytes") + + # Check if it's a true echo + if response == message: + print("SUCCESS: Received message matches sent message!") + else: + print("FAILURE: Received message differs from sent message!") + if len(response) != len(message): + print(f"Length mismatch: sent {len(message)}, received {len(response)}") + + except ConnectionRefusedError: + print("Connection failed! Make sure the server is running.") + except Exception as e: + print(f"An error occurred: {e}") + +if __name__ == "__main__": + # Test with a simple message + test_echo_server() + + # Test with a longer message + test_echo_server(message="This is a longer message to test the echo server's ability to handle larger strings!") + + # Test with special characters + test_echo_server(message="Special chars: !@#$%^&*()") + + # Test with a large message + large_message = "X" * 10000 # 10KB of data + test_echo_server(message=large_message) \ No newline at end of file diff --git a/main.c b/main.c deleted file mode 100644 index b9ff1bd..0000000 --- a/main.c +++ /dev/null @@ -1,79 +0,0 @@ -#include -#include -#include -#include "main.h" -#include "data.h" - -#define PORT 40000 -#define BUFFER_SIZE 1024 - - -int main() -{ - // load_file(); - - WSADATA WSAData; - - SOCKET client; - - SOCKADDR_IN serverAddr, clientAddr; - - WSAStartup(MAKEWORD(2,0), &WSAData); - SOCKET server = socket(AF_INET, SOCK_STREAM, 0); - - serverAddr.sin_addr.s_addr = INADDR_ANY; - serverAddr.sin_family = AF_INET; - serverAddr.sin_port = htons(PORT); - - bind(server, (SOCKADDR *)&serverAddr, sizeof(serverAddr)); - listen(server, 0); - - printf("Listening for incoming connections...\n"); - - char buffer[BUFFER_SIZE] = {0}; - int clientAddrSize = sizeof(clientAddr); - int recieved; - char_array_t *reply = char_array_create(1024); - while((client = accept(server, (SOCKADDR *)&clientAddr, &clientAddrSize)) != INVALID_SOCKET) - { - printf(" Client connected!\n"); - while ((recieved = recv(client, buffer, sizeof(buffer), 0)) > 0) { - printf(" Client says: |%.1024s|\n",buffer); - char_array_append(reply, buffer, recieved); - if (buffer[recieved] == '\0') { - break; - } - memset(buffer, 0, sizeof(buffer)); - Sleep(10); - } - - printf(" Sending back...\n"); - - printf(" Sending back: |%d| \n", reply->size); - send(client, reply->data,reply->size,0); - char_array_wipe(reply); - - closesocket(client); - printf("Client disconnected.\n"); - } -} - -void echo(SOCKET client) { - char buffer[BUFFER_SIZE] = {0}; - char_array_t *reply = char_array_create(BUFFER_SIZE); - int bytesReceived; - while ((bytesReceived = recv(client, buffer, sizeof(buffer), 0)) > 0) { - printf(" Client says: |%.1024s|\n",buffer); - char_array_append(reply, buffer, bytesReceived); - if (buffer[bytesReceived] == '\0') { - break; - } - memset(buffer, 0, sizeof(buffer)); - Sleep(10); - } - printf(" Sending back...\n"); - - printf(" Sending back: |%llu| \n", reply->size); - send(client, reply->data,reply->size,0); - closesocket(client); -} \ No newline at end of file diff --git a/main.h b/main.h deleted file mode 100644 index f7ecf77..0000000 --- a/main.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Created by Ajurna on 27/07/2025. -// - -#ifndef MAIN_H -#define MAIN_H - -#endif //MAIN_H - - -typedef struct ReplyArray { - size_t size; - size_t capacity; - char *data; -} array_t; - -array_t *array_create(int size); -void array_destroy(array_t *array); -void array_append(array_t *array, char *value, size_t length); -void array_print(const array_t *array); -void array_wipe(array_t *array); \ No newline at end of file diff --git a/parallel_echo_client_test.py b/parallel_echo_client_test.py new file mode 100644 index 0000000..8f7f6f1 --- /dev/null +++ b/parallel_echo_client_test.py @@ -0,0 +1,84 @@ +import socket +import threading +import time +import random +import string + +def random_string(length): + """Generate a random string of fixed length""" + return ''.join(random.choices(string.ascii_letters + string.digits, k=length)) + +def echo_client(client_id, message): + """Individual client function that connects and sends/receives data""" + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + try: + s.connect(('localhost', 40000)) + print(f"Client {client_id}: Connected") + + # Send the message + print(f"Client {client_id}: Sending message of length {len(message)}") + s.sendall(message.encode()) + + # Receive the response in chunks + chunks = [] + bytes_received = 0 + while bytes_received < len(message): + chunk = s.recv(1024) + if not chunk: + break + chunks.append(chunk) + bytes_received += len(chunk) + time.sleep(0.1) + + response = b''.join(chunks).decode() + + # Verify response + if response == message: + print(f"Client {client_id}: SUCCESS - Message verified ({len(response)} bytes)") + else: + print(f"Client {client_id}: FAILURE - Message mismatch!") + print(f"Client {client_id}: Expected length: {len(message)}, Got: {len(response)}") + + except Exception as e: + print(f"Client {client_id}: Error - {str(e)}") + +def run_parallel_test(num_clients=5, message_size_range=(100, 5000)): + """Run multiple clients in parallel""" + threads = [] + + print(f"Starting parallel test with {num_clients} clients...") + + # Create and start threads + for i in range(num_clients): + # Generate random message size between min and max range + msg_size = random.randint(*message_size_range) + message = random_string(msg_size) + + thread = threading.Thread(target=echo_client, args=(i, message)) + threads.append(thread) + thread.start() + # Small delay between starting threads + time.sleep(0.1) + + # Wait for all threads to complete + for thread in threads: + thread.join() + + print("All clients finished") + +if __name__ == "__main__": + # Test 1: Few clients with small messages + print("\nTest 1: 3 parallel clients with small messages") + run_parallel_test(num_clients=3, message_size_range=(100, 500)) + + time.sleep(1) # Wait between tests + + # Test 2: More clients with varying message sizes + print("\nTest 2: 5 parallel clients with varying message sizes") + run_parallel_test(num_clients=5, message_size_range=(1000, 5000)) + + time.sleep(1) # Wait between tests + + # Test 3: Stress test with many clients + print("\nTest 3: Stress test with 10 parallel clients") + run_parallel_test(num_clients=10, message_size_range=(500, 10000)) diff --git a/prime_time_server_tests.py b/prime_time_server_tests.py new file mode 100644 index 0000000..758d433 --- /dev/null +++ b/prime_time_server_tests.py @@ -0,0 +1,163 @@ +import socket +import json +import threading +import time +import random + +def send_request(sock, request): + """Send a request and get response""" + request_str = json.dumps(request) + '\n' + sock.sendall(request_str.encode()) + + response = sock.recv(1024).decode() + try: + return json.loads(response.strip()) + except json.JSONDecodeError: + return response.strip() + +def batch_test_client(): + """Run a test with 50 problems in quick succession""" + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: + try: + sock.connect(('localhost', 40000)) + print("Batch Test: Connected") + + # Generate 50 test cases with known prime and non-prime numbers + test_numbers = ( + # Known primes + [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47] + + # Non-primes + [4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25] + + # Edge cases + [0, 1, -1, 1.5, 2.0] + + # Larger numbers + [97, 100, 121, 169, 289, 361, 529, 841, 961, 1001] + + # Random numbers to complete 50 + [random.randint(1000, 10000) for _ in range(5)] + ) + + success_count = 0 + start_time = time.time() + + for i, number in enumerate(test_numbers): + request = {"method": "isPrime", "number": number} + + try: + response = send_request(sock, request) + expected_prime = ( + isinstance(number, int) and + number > 1 and + all(number % i != 0 for i in range(2, int(number ** 0.5) + 1)) + ) + expected = {"method": "isPrime", "prime": expected_prime} + + if response == expected: + success_count += 1 + print(f"✓ Test {i+1}/50: {number} -> {response['prime']}") + else: + print(f"✗ Test {i+1}/50: {number} Expected: {expected}, Got: {response}") + + except Exception as e: + print(f"Error on test {i+1}/50 with number {number}: {e}") + break + + end_time = time.time() + duration = end_time - start_time + + print(f"\nBatch Test Results:") + print(f"Total tests: 50") + print(f"Successful: {success_count}") + print(f"Failed: {50 - success_count}") + print(f"Time taken: {duration:.2f} seconds") + print(f"Average time per request: {(duration/50)*1000:.2f} ms") + + except ConnectionRefusedError: + print("Batch Test: Connection failed! Is the server running?") + +def test_client(test_cases, client_id): + """Run a series of test cases""" + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: + try: + sock.connect(('localhost', 40000)) + print(f"Client {client_id}: Connected") + + for i, test in enumerate(test_cases): + request = test['request'] + expected = test['expected'] + desc = test.get('desc', 'No description') + + print(f"\nClient {client_id}: Test {i + 1} - {desc}") + print(f"Request: {request}") + + try: + response = send_request(sock, request) + print(f"Response: {response}") + + if test.get('should_disconnect', False): + try: + send_request(sock, {"method": "isPrime", "number": 2}) + print("ERROR: Server didn't disconnect when it should have") + except: + print("SUCCESS: Server correctly disconnected") + break + + if response == expected: + print("SUCCESS: Response matches expected") + else: + print(f"FAILURE: Expected {expected}, got {response}") + + except Exception as e: + print(f"Error during test: {e}") + if test.get('should_disconnect', False): + print("SUCCESS: Expected disconnect occurred") + else: + print("FAILURE: Unexpected error") + break + + except ConnectionRefusedError: + print(f"Client {client_id}: Connection failed! Is the server running?") + +def run_all_tests(): + print("Starting Prime Time Server tests...") + + # Test 1: Basic functionality + print("\nTest 1: Single client with valid requests") + test_client([{ + 'desc': "Basic prime test", + 'request': {"method": "isPrime", "number": 7}, + 'expected': {"method": "isPrime", "prime": True} + }], 0) + + time.sleep(1) + + # Test 2: Malformed request + print("\nTest 2: Single client with malformed request") + test_client([{ + 'desc': "Malformed request test", + 'request': {"method": "wrong", "number": 7}, + 'expected': "malformed", + 'should_disconnect': True + }], 0) + + time.sleep(1) + + # Test 3: Batch test with 50 problems + print("\nTest 3: Batch test with 50 problems") + batch_test_client() + + time.sleep(1) + + # Test 4: Multiple parallel clients + print("\nTest 4: Multiple parallel clients") + threads = [] + for i in range(5): + thread = threading.Thread(target=batch_test_client) + threads.append(thread) + thread.start() + time.sleep(0.1) + + for thread in threads: + thread.join() + +if __name__ == "__main__": + run_all_tests() \ No newline at end of file diff --git a/server00.c b/server00.c new file mode 100644 index 0000000..5c8a61b --- /dev/null +++ b/server00.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include "server00.h" +#include "data.h" + +#define PORT 40000 +#define BUFFER_SIZE 1024 + + + +int main() +{ + // load_file(); + + WSADATA WSAData; + + SOCKET client; + + SOCKADDR_IN serverAddr, clientAddr; + + WSAStartup(MAKEWORD(2,0), &WSAData); + SOCKET server = socket(AF_INET, SOCK_STREAM, 0); + + serverAddr.sin_addr.s_addr = INADDR_ANY; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(PORT); + + bind(server, (SOCKADDR *)&serverAddr, sizeof(serverAddr)); + listen(server, 0); + + printf("Listening for incoming connections...\n"); + + int clientAddrSize = sizeof(clientAddr); + int connection_number = 0; + char_array_t *reply = char_array_create(1024); + while((client = accept(server, (SOCKADDR *)&clientAddr, &clientAddrSize)) != INVALID_SOCKET) + { + struct EchoArgs *args = malloc(sizeof(struct EchoArgs)); + args->client = client; + args->connection = connection_number++; + pthread_t thread; + pthread_create(&thread, nullptr, echo,(void *) args); + } +} + +void *echo(void *args) { + const auto echoArgs = (struct EchoArgs *) args; + char buffer[BUFFER_SIZE] = {0}; + char_array_t *reply = char_array_create(BUFFER_SIZE); + int bytesReceived; + int bytesTotal = 0; + while ((bytesReceived = recv(echoArgs->client, buffer, sizeof(buffer), 0)) > 0) { + // printf(" Client {%d} says: |%.1024s|\n", echoArgs->connection ,buffer); + printf("Client sent {%d}: |%d| \n", echoArgs->connection, bytesReceived); + + char_array_append(reply, buffer, bytesReceived); + bytesTotal += bytesReceived; + memset(buffer, 0, sizeof(buffer)); + Sleep(20); + } + printf("Total bytes received {%d}: %d\n", echoArgs->connection, bytesTotal); + printf("Sending back {%d}: |%llu| \n", echoArgs->connection, reply->size); + send(echoArgs->client, reply->data,reply->size,0); + closesocket(echoArgs->client); + free(echoArgs); + return NULL; +} \ No newline at end of file diff --git a/server00.h b/server00.h new file mode 100644 index 0000000..7c63a30 --- /dev/null +++ b/server00.h @@ -0,0 +1,17 @@ +// +// Created by Ajurna on 27/07/2025. +// + +#ifndef MAIN_H +#define MAIN_H + +#endif //MAIN_H +#include +#pragma once + +struct EchoArgs { + int connection; + SOCKET client; +}; + +void *echo(void *args); \ No newline at end of file diff --git a/server01.c b/server01.c new file mode 100644 index 0000000..42076cb --- /dev/null +++ b/server01.c @@ -0,0 +1,124 @@ +// +// Created by PeterDwyer on 28/07/2025. +// + +#include "server01.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include "data.h" + +#define IS_PRIME "{\"method\":\"isPrime\",\"prime\":true}\n" +#define IS_NOT_PRIME "{\"method\":\"isPrime\",\"prime\":false}\n" +#define IS_PRIME_ERROR "{\"method\":\"isPrime\",\"error\":true}\n" +int main() { + SOCKET server = get_listen_socket(); + SOCKADDR_IN serverAddr, clientAddr; + SOCKET client; + int clientAddrSize = sizeof(clientAddr); + int connection_number = 1; + while((client = accept(server, (SOCKADDR *)&clientAddr, &clientAddrSize)) != INVALID_SOCKET) + { + handle_args_t *args = malloc(sizeof(handle_args_t)); + args->client = client; + args->connection = connection_number++; + pthread_t thread; + pthread_create(&thread, nullptr, handle_connection, args); + } + return 0; +} + +void *handle_connection(void *args) { + handle_args_t *handleArgs = args; + char buffer[1024] = {0}; + int bytesReceived; + char_array_t *data = char_array_create(1024); + while ((bytesReceived = recv(handleArgs->client, buffer, sizeof(buffer), 0)) > 0) { + printf("Client sent {%d}: |%d| \n", handleArgs->connection, bytesReceived); + char_array_append(data, buffer, bytesReceived); + char *request; + while ((request = char_array_get_until_char(data, '\n')) != NULL) { + parse_request(handleArgs, request, data); + } + + + + memset(buffer, 0, sizeof(buffer)); + } + pthread_exit(NULL); +} + +void parse_request(handle_args_t *handleArgs, const char *request, char_array_t *data) { + if (request != NULL) { + const json_object *obj = json_tokener_parse(request); + if (obj == NULL) { + printf("{%d} Failed to parse json\n", handleArgs->connection); + send(handleArgs->client, IS_PRIME_ERROR, strlen(IS_PRIME_ERROR), 0); + char_array_destroy(data); + closesocket(handleArgs->client); + pthread_exit(NULL); + } + json_object *method_obj = json_object_object_get(obj, "method"); + json_object *number_obj = json_object_object_get(obj, "number"); + if (method_obj == NULL || number_obj == NULL) { + printf("{%d} Missing Fields\n", handleArgs->connection); + send(handleArgs->client, IS_PRIME_ERROR, strlen(IS_PRIME_ERROR), 0); + char_array_destroy(data); + closesocket(handleArgs->client); + pthread_exit(NULL); + } + const int number_type = json_object_get_type(number_obj); + if (!(json_object_is_type(method_obj, json_type_string) && (number_type== json_type_double || number_type == json_type_int))) { + printf("{%d} Fields Wrong Type\n", handleArgs->connection); + send(handleArgs->client, IS_PRIME_ERROR, strlen(IS_PRIME_ERROR), 0); + char_array_destroy(data); + closesocket(handleArgs->client); + pthread_exit(NULL); + } + const char *method = json_object_get_string(method_obj); + if (strcmp(method, "isPrime") != 0) { + printf("{%d} Invalid method\n", handleArgs->connection); + send(handleArgs->client, IS_PRIME_ERROR, strlen(IS_PRIME_ERROR), 0); + char_array_destroy(data); + closesocket(handleArgs->client); + } + if (number_type == json_type_double) { + printf("{%d} Floats cannot be prime\n", handleArgs->connection); + send(handleArgs->client, IS_NOT_PRIME, strlen(IS_NOT_PRIME), 0); + } + const int number = json_object_get_int(number_obj); + bool number_is_prime; + if (number == INT32_MAX) { + number_is_prime = false; + } else { + number_is_prime = is_prime(number); + } + + printf("{%d} '%d' is prime: %d\n", handleArgs->connection, number, number_is_prime); + char *response = number_is_prime ? IS_PRIME : IS_NOT_PRIME; + send(handleArgs->client, response, strlen(response), 0); + } +} + +bool is_prime(const int number) { + if (number == 2) { + return true; + } + if (number < 2 || number % 2 == 0) { + return false; + } + + const int limit = (int)sqrt(number); + for (int i = 3; i <= limit; i+=2) { + if (number % i == 0) { + return false; + } + } + return true; +} \ No newline at end of file diff --git a/server01.h b/server01.h new file mode 100644 index 0000000..d48814c --- /dev/null +++ b/server01.h @@ -0,0 +1,21 @@ +// +// Created by PeterDwyer on 28/07/2025. +// + +#ifndef SERVER01_H +#define SERVER01_H +#include + +#include "data.h" +#pragma once + +typedef struct HandleArgs { + int connection; + SOCKET client; +} handle_args_t; + +#endif //SERVER01_H + +bool is_prime(const int number); +void *handle_connection(void *args); +void parse_request(handle_args_t *handleArgs, const char *request, char_array_t *data); \ No newline at end of file