diff --git a/04_intro_to_sockets/README.md b/04_intro_to_sockets/README.md index eb91d03..d222604 100644 --- a/04_intro_to_sockets/README.md +++ b/04_intro_to_sockets/README.md @@ -7,5 +7,14 @@ a LED, a button and a temperature sensor. ```bash $ make -$ ./sockets +``` + +## Testing with nc + +Clients: +```bash +# TCP +$ nc -l 1234 +# UDP +$ nc -ul 1234 ``` diff --git a/04_intro_to_sockets/lib/sockets.c b/04_intro_to_sockets/lib/sockets.c index 7031a77..a7123fb 100644 --- a/04_intro_to_sockets/lib/sockets.c +++ b/04_intro_to_sockets/lib/sockets.c @@ -11,8 +11,9 @@ static void error_handling(char *message, int sock) { perror(message); + if (sock != -1) + close(sock); close(sock); - exit(1); } int tcp_create_socket() { @@ -111,3 +112,82 @@ void process_request(int clnt_sock) { write(clnt_sock, message, strlen(message)); } +int udp_create_socket() { + int sock = socket(PF_INET, SOCK_DGRAM, 0); + if (sock == -1) { + error_handling("UDP socket creation failed", sock); + } + return sock; +} + +void udp_bind_socket(int sock, int port) { + struct sockaddr_in serv_addr; + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(port); + + if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) { + error_handling("UDP bind failed", sock); + } +} + +void udp_send_message(int sock, char *server_ip, int port, char *message) { + struct sockaddr_in dest_addr; + memset(&dest_addr, 0, sizeof(dest_addr)); + dest_addr.sin_family = AF_INET; + dest_addr.sin_addr.s_addr = inet_addr(server_ip); + dest_addr.sin_port = htons(port); + + sendto(sock, message, strlen(message), 0, + (struct sockaddr *)&dest_addr, sizeof(dest_addr)); +} + +char *udp_receive_message(int sock) { + struct sockaddr_in from_addr; + socklen_t from_addr_size = sizeof(from_addr); + char *buffer = malloc(BUFFER_SIZE); + if (buffer == NULL) { + error_handling("Failed to allocate memory for buffer", sock); + } + + int str_len = recvfrom(sock, buffer, BUFFER_SIZE, 0, + (struct sockaddr *)&from_addr, &from_addr_size); + if (str_len == -1) { + free(buffer); + error_handling("recvfrom() failed", sock); + } + + buffer[str_len] = '\0'; // Null-terminate the string + return buffer; +} + +void handle_udp_client(int serv_sock) { + struct sockaddr_in clnt_addr; + socklen_t clnt_addr_size = sizeof(clnt_addr); + char buffer[BUFFER_SIZE]; + + while (1) { + int str_len = recvfrom(serv_sock, buffer, BUFFER_SIZE - 1, 0, + (struct sockaddr*)&clnt_addr, &clnt_addr_size); + if (str_len == -1) + error_handling("recvfrom() failed", serv_sock); + + buffer[str_len] = '\0'; // Null-terminate the string + + time_t t = time(NULL); + struct tm *timeinfo; + + if (strcmp(buffer, "1") == 0) { + timeinfo = localtime(&t); // Local time + } else { + timeinfo = gmtime(&t); // GMT time + } + + strftime(buffer, BUFFER_SIZE, "%Y-%m-%d %H:%M:%S", timeinfo); + + // Prepare a response - could be customized based on the message + sendto(serv_sock, buffer, strlen(buffer), 0, + (struct sockaddr*)&clnt_addr, clnt_addr_size); + } +} diff --git a/04_intro_to_sockets/lib/sockets.h b/04_intro_to_sockets/lib/sockets.h index cf6322d..467f9c9 100644 --- a/04_intro_to_sockets/lib/sockets.h +++ b/04_intro_to_sockets/lib/sockets.h @@ -19,4 +19,15 @@ int tcp_accept(int serv_sock); // Function to process a client request void process_request(int clnt_sock); + +int udp_create_socket(); + +void udp_send_message(int sock, char *server_ip, int port, char *message); + +void udp_bind_socket(int sock, int port); + +char* udp_receive_message(int sock); + +void handle_udp_client(int serv_sock); + #endif // SOCKETS_LIB_H diff --git a/04_intro_to_sockets/src/daytimeUDPCli.c b/04_intro_to_sockets/src/daytimeUDPCli.c new file mode 100644 index 0000000..0329471 --- /dev/null +++ b/04_intro_to_sockets/src/daytimeUDPCli.c @@ -0,0 +1,19 @@ +#include // For printf() +#include // For close() +#include // For exit(), atoi() +#include "sockets.h" + +int main(int argc, char *argv[]) { + if (argc != 4) { + printf("Usage : %s \n", argv[0]); + exit(1); + } + + int sock = udp_create_socket(); + udp_send_message(sock, argv[1], atoi(argv[2]), argv[3]); + char *response = udp_receive_message(sock); + printf("Received from server: %s\n", response); + free(response); + close(sock); + return 0; +} diff --git a/04_intro_to_sockets/src/daytimeUDPSrv.c b/04_intro_to_sockets/src/daytimeUDPSrv.c new file mode 100644 index 0000000..0bd6401 --- /dev/null +++ b/04_intro_to_sockets/src/daytimeUDPSrv.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include "sockets.h" + +int main(int argc, char *argv[]) { + if (argc != 2) { + printf("Usage: %s \n", argv[0]); + exit(1); + } + + int sock = udp_create_socket(); + udp_bind_socket(sock, atoi(argv[1])); + handle_udp_client(sock); + return 0; +}