From 0e6ef7dc8a02c35ec5f0dbcd31213c3dfbc4f95b Mon Sep 17 00:00:00 2001 From: Vinicius Date: Sun, 26 Nov 2023 23:28:17 -0300 Subject: [PATCH] Socket TCP, UDP and UNIXDOMAIN connetions implemented --- CMakeLists.txt | 5 ++ bin/client | Bin 0 -> 17464 bytes bin/server | Bin 0 -> 17432 bytes dependences.dot | 27 +++++++++ dependences.png | Bin 0 -> 46098 bytes src/client.c | 145 +++++++++++++++++++++++++++++++----------------- src/server.c | 129 +++++++++++++++++++++++++++++++++--------- 7 files changed, 228 insertions(+), 78 deletions(-) create mode 100755 bin/client create mode 100755 bin/server create mode 100644 dependences.dot create mode 100644 dependences.png diff --git a/CMakeLists.txt b/CMakeLists.txt index 26c451c..d821127 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,9 @@ cmake_minimum_required(VERSION 2.8) project(pingpong) + +execute_process( + COMMAND mkdir -p bin +) + add_executable(./bin/server ./src/server.c) add_executable(./bin/client ./src/client.c) diff --git a/bin/client b/bin/client new file mode 100755 index 0000000000000000000000000000000000000000..5cb54e6bf6fe8d92d2a177a652967b3e3982e9b9 GIT binary patch literal 17464 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 YS#YvlsY|D6Hv4;TH8f^e3@j}BZ%m|ZQ~&?~ literal 0 HcmV?d00001 diff --git a/bin/server b/bin/server new file mode 100755 index 0000000000000000000000000000000000000000..a270f934e6fa60761336f25b8f538cde6a2d890e GIT binary patch literal 17432 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 L#w3S legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "./bin/client", shape = egg ]; + "node1" [ label = "./bin/server", shape = egg ]; +} diff --git a/dependences.png b/dependences.png new file mode 100644 index 0000000000000000000000000000000000000000..72ffa9d0c78fa85498e20e203e60a6ccfcf27012 GIT binary patch literal 46098 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 W-=3Tq7W+oQAHy+b261{bH~tT}V6+kd literal 0 HcmV?d00001 diff --git a/src/client.c b/src/client.c index bec978d..d65b96e 100644 --- a/src/client.c +++ b/src/client.c @@ -16,28 +16,42 @@ #define SOCKET_ERROR_CODE -1 // Socket create, Connection server, Receive buffer to server code error #define SYSTEM_EXIT_FAILED 1 // Operating System program error response #define SYSTEM_EXIT_SUCCESS 0 // Operating System program success response - - -#define KB 1024 +#define NUM_OF_ARGUMENTS 3 +#define TCP_SOCKET_FLAG 1 +#define UDP_SOCKET_FLAG 2 +#define UNIX_SOCKET_FLAG 3 float times[N]; -float send_elapsed_time_ms = 0.00; -float receive_elapsed_time_ms = 0.00; +int num_of_read_bytes = 0; +typedef struct sockaddr_in socket_address; +size_t buffer_size; +int socket_type; + +int domain, type, protocol; + +float elapsed_time_ms = 0.00; + +ssize_t (*send_generic_fn)(int __fd, const void *__buf, size_t __n, int __flags); +ssize_t (*recv_generic_fn)(int __fd, void *__buf, size_t __n, int __flags); + +int domain, type, protocol, sin_family, address, sock; typedef struct sockaddr_in socket_address; +void panic(char* message) +{ + perror(message); + exit(SYSTEM_EXIT_FAILED); +} + int init_socket() { - // AF_INET -> IPV4 Family - // SOCK_STREAM -> TCP Socket initialization - // IPPROTO_TCP -> TCP Explicit protocol - int client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + int client_socket = socket(sin_family, sock, IPPROTO_TCP); if(client_socket == SOCKET_ERROR_CODE) { - perror("Socket create failed!\n"); - exit(SYSTEM_EXIT_FAILED); + panic("Socket create failed!\n"); } return client_socket; @@ -47,9 +61,9 @@ socket_address config_server_address() { socket_address server_address; - server_address.sin_family = AF_INET; // IPV4 ips family + server_address.sin_family = sin_family; server_address.sin_port = htons(SERVER_PORT); - server_address.sin_addr.s_addr = inet_addr(HOST_IP); + server_address.sin_addr.s_addr = address; return server_address; } @@ -65,26 +79,32 @@ void connect_to_server(int client_socket, socket_address server_address) if(connection_response == SOCKET_ERROR_CODE) { - perror("Server connection error\n"); + close(client_socket); - exit(SYSTEM_EXIT_FAILED); + panic("Server connection error\n"); } } int receive_buffer(int client_socket, int buffer_size) { - ssize_t bytes_read; - int received_buffer[buffer_size]; - - recv(client_socket, received_buffer, buffer_size, 0); - + recv_generic_fn(client_socket, received_buffer, buffer_size, 0); + + for(int i = 0; i < buffer_size; i++) + { + printf("%d", received_buffer[i]); + } + printf("\nRECEBIDO\n"); } - void send_buffer(int client_socket, int buffer[], size_t buffer_size) { - send(client_socket, buffer, buffer_size, 0); + for(int i = 0; i < num_of_read_bytes; i++) + { + printf("ENVIO %d\n", i); + send_generic_fn(client_socket, buffer, buffer_size, 0); + receive_buffer(client_socket, buffer_size); + } } void controlc_handler() @@ -98,42 +118,69 @@ void socket_listen(int client_socket, int buffer[], size_t buffer_size) if(signal(SIGINT, controlc_handler) == SIG_ERR) { - perror("Signal create error!"); - exit(SYSTEM_EXIT_FAILED); + panic("Signal create error!"); } - clock_t start_send_time = clock(); + clock_t start_time = clock(); send_buffer(client_socket, buffer, buffer_size); - clock_t end_send_time = clock(); + clock_t end_time = clock(); - clock_t send_difference = (end_send_time - start_send_time); - send_elapsed_time_ms = ((float)send_difference / (CLOCKS_PER_SEC/1000)); - - clock_t start_receive_time = clock(); - receive_buffer(client_socket, buffer_size); - clock_t end_receive_time = clock(); - - clock_t receive_difference = (end_receive_time - start_receive_time); - receive_elapsed_time_ms = ((float)receive_difference / (CLOCKS_PER_SEC/1000)); + elapsed_time_ms = ((float)(end_time - start_time) / (CLOCKS_PER_SEC/1000)); } -float calculate() + +void attribuite_socket_type(int socket_type) { - - float average_total = 0.00; - - for(int i = 0; i < N; i++){ - average_total += times[i]; + switch (socket_type) + { + case TCP_SOCKET_FLAG: // TCP SOCKET + sin_family = AF_INET; + send_generic_fn = &send; + recv_generic_fn = &recv; + address = inet_addr(HOST_IP); + sock = SOCK_STREAM; + break; + + case UDP_SOCKET_FLAG: // UDP SOCKET + send_generic_fn = &sendto; + recv_generic_fn = &recvfrom; + address = INADDR_ANY; + sock = SOCK_DGRAM; + break; + + case UNIX_SOCKET_FLAG: // UNIXDOMAIN SOCKET + sin_family = AF_UNIX; + send_generic_fn = &send; + recv_generic_fn = &recv; + address = inet_addr(HOST_IP); + sock = SOCK_STREAM; + break; + + default: + panic("Value error!"); + break; } - - return average_total; } +void get_args(int argc, char** argv) +{ + if(argc > NUM_OF_ARGUMENTS) + { + buffer_size = (int)atoi(argv[1]); + num_of_read_bytes = (int)atoi(argv[2]); + socket_type = (int)atoi(argv[3]); + }else + { + panic("Argument is missing!"); + } + +} int main(int argc, char** argv) { - size_t buffer_size = (int)atoi(argv[1]); + get_args(argc, argv); + attribuite_socket_type(socket_type); int buffer[buffer_size]; @@ -149,15 +196,9 @@ int main(int argc, char** argv) connect_to_server(client_socket, server_address); - for(int i = 0; i < N; i++){ + socket_listen(client_socket, buffer, buffer_size); - socket_listen(client_socket, buffer, buffer_size); - times[i] = send_elapsed_time_ms + receive_elapsed_time_ms; - } - - float average = calculate(); - - printf("%lf\n", (float)(average/(float)N)); + printf("%lf\n", (float)(elapsed_time_ms)); return SYSTEM_EXIT_SUCCESS; } diff --git a/src/server.c b/src/server.c index 5c708d4..8df95d5 100644 --- a/src/server.c +++ b/src/server.c @@ -10,24 +10,47 @@ #define TRUE 1 #define HOST_IP "127.0.0.1" // IPV4 loopback address #define SERVER_PORT 8481 // Server port -#define MAX_CONNECTIONS 10 // Num max client connected simultaneously +#define MAX_CONNECTIONS 1 // Num max client connected simultaneously #define SOCKET_ERROR_CODE -1 // Socket create, Connection server, Receive buffer to server code error #define SYSTEM_EXIT_FAILED 1 // Operating System program error response #define SYSTEM_EXIT_SUCCESS 0 // Operating System program success response -#define KB 1024 +#define NUM_OF_ARGUMENTS 3 +#define TCP_SOCKET_FLAG 1 +#define UDP_SOCKET_FLAG 2 +#define UNIX_SOCKET_FLAG 3 +int num_of_read_bytes = 0; typedef struct sockaddr_in socket_address; +size_t buffer_size; +int socket_type; + +ssize_t (*send_fn); +ssize_t recv_fn = NULL; + +ssize_t (*send_generic_fn); +ssize_t (*recv_generic_fn); + + + +//(int __fd, void *__buf, size_t __n, int __flags); + +int domain, type, protocol, sin_family, address, sock; + +void panic(char* message) +{ + perror(message); + exit(SYSTEM_EXIT_FAILED); +} int create_socket() { int server_socket; - server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + server_socket = socket(sin_family, sock, IPPROTO_TCP); if(server_socket == SOCKET_ERROR_CODE) { - perror("Socket create failed!"); - exit(SYSTEM_EXIT_FAILED); + panic("Socket create failed!"); } return server_socket; @@ -36,10 +59,10 @@ int create_socket() socket_address config_server_address() { socket_address server_address; - - server_address.sin_family = AF_INET; // IPV4 ips family + + server_address.sin_family = sin_family; server_address.sin_port = htons(SERVER_PORT); - server_address.sin_addr.s_addr = inet_addr(HOST_IP); + server_address.sin_addr.s_addr = address; return server_address; } @@ -53,9 +76,8 @@ void bind_server(int server_socket, socket_address server_address) if(server_bind_response == SOCKET_ERROR_CODE) { - perror("Bind server error"); close(server_socket); - exit(SYSTEM_EXIT_FAILED); + panic("Bind server error"); } } @@ -67,34 +89,30 @@ int accept_connection(int client_socket, int server_socket, socket_address clien if(client_socket == SYSTEM_EXIT_FAILED) { - perror("Accept connection error!"); - exit(SYSTEM_EXIT_FAILED); - + panic("Accept connection error!"); }else{ return client_socket; } - } void send_buffer(int client_socket, int buffer[], int buffer_size) { - send(client_socket, buffer, buffer_size, 0); + send_fn(client_socket, buffer, buffer_size, 0); } - int receive_buffer(int client_socket, int buffer_size) { ssize_t bytes_read; int received_buffer[buffer_size]; - - while((bytes_read = recv(client_socket, received_buffer, buffer_size, 0)) > 0) + + for(int i = 0; i < num_of_read_bytes; i++) { - - received_buffer[bytes_read] = '\0'; - - send_buffer(client_socket, received_buffer, buffer_size); + while((bytes_read = recv_fn(client_socket, received_buffer, buffer_size, 0)) > 0) + { + send_buffer(client_socket, received_buffer, buffer_size); + } } } @@ -104,15 +122,14 @@ void controlc_handler() exit(SYSTEM_EXIT_SUCCESS); } - void server_listen(int client_socket, int server_socket, socket_address client_address, socklen_t client_addr_len, int buffer_size) { if (listen(server_socket, MAX_CONNECTIONS) == SOCKET_ERROR_CODE) { - perror("Listening mode error"); + close(server_socket); - exit(SYSTEM_EXIT_FAILED); + panic("Listening mode error"); } printf("[SERVER] - Server TCP listening on port %d...\n", SERVER_PORT); @@ -121,10 +138,68 @@ void server_listen(int client_socket, int server_socket, socket_address client_a receive_buffer(client_socket, buffer_size); } +void attribuite_socket_type(int socket_type) +{ + switch (socket_type) + { + case TCP_SOCKET_FLAG: // TCP SOCKET + sin_family = AF_INET; + + send_generic_fn = &send; + recv_generic_fn = &recv; + address = inet_addr(HOST_IP); + sock = SOCK_STREAM; + break; + + case UDP_SOCKET_FLAG: // UDP SOCKET + ssize_t (*send_generic_fn)(int __fd, const void *__buf, size_t __n, int __flags, __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len); + ssize_t (*recv_generic_fn)(int __fd, void *__restrict __buf, size_t __n, int __flags, __SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len); + + send_generic_fn = &sendto; + recv_generic_fn = &recvfrom; + + send_fn = &send_generic_fn; + recv_fn = &recv_generic_fn; + + address = INADDR_ANY; + sock = SOCK_DGRAM; + break; + + case UNIX_SOCKET_FLAG: // UNIXDOMAIN SOCKET + sin_family = AF_UNIX; + send_generic_fn(int __fd, const void *__buf, size_t __n, int __flags); + send_generic_fn = &send; + recv_generic_fn = &recv; + address = inet_addr(HOST_IP); + sock = SOCK_STREAM; + break; + + default: + panic("Value error!"); + break; + } +} + +void get_args(int argc, char** argv) +{ + if(argc > NUM_OF_ARGUMENTS) + { + buffer_size = (int)atoi(argv[1]); + num_of_read_bytes = (int)atoi(argv[2]); + socket_type = (int)atoi(argv[3]); + }else + { + panic("Argument is missing!"); + } + +} + int main(int argc, char** argv) { - size_t buffer_size = 8192; + get_args(argc, argv); + attribuite_socket_type(socket_type); + int buffer[buffer_size]; int server_socket, client_socket; @@ -139,4 +214,6 @@ int main(int argc, char** argv) bind_server(server_socket, server_address); server_listen(client_socket, server_socket, client_address, client_addr_len, buffer_size); + + return SYSTEM_EXIT_SUCCESS; }