From 83a823980588a1c933ee444cd64dfb9587ae248d Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Tue, 21 Jul 2020 22:59:18 -0400 Subject: [PATCH] [enhancement] Client_server folder code updated for windows OS as well. (#577) * update codes to run on Windows platform as well * added cmake for client_server * added scope parameters * force use of unistd.h in non-windows * use size_t instead of int * use unsigned int instead of size_t * clang-tidy fixes for ac0991eb5103ee6b36f74ba6fd1845dae371707b * updated UDP server-client as well * use unsigned int * added documentation * spell correction Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- CMakeLists.txt | 1 + client_server/CMakeLists.txt | 45 +++++++++++++++++++ client_server/client.c | 66 ++++++++++++++++++++++++--- client_server/server.c | 87 +++++++++++++++++++++++++++++------- client_server/udp_client.c | 51 +++++++++++++++++---- client_server/udp_server.c | 53 ++++++++++++++++++---- 6 files changed, 263 insertions(+), 40 deletions(-) create mode 100644 client_server/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 03ed954b..feaa34f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ add_subdirectory(sorting) add_subdirectory(graphics) add_subdirectory(searching) add_subdirectory(conversions) +add_subdirectory(client_server) add_subdirectory(project_euler) add_subdirectory(machine_learning) add_subdirectory(numerical_methods) diff --git a/client_server/CMakeLists.txt b/client_server/CMakeLists.txt new file mode 100644 index 00000000..70d08ad8 --- /dev/null +++ b/client_server/CMakeLists.txt @@ -0,0 +1,45 @@ +# include(CheckIncludeFile) +# check_include_file(arpa/inet.h ARPA_HEADERS) +# if(NOT ARPA_HEADERS) +# check_include_file(winsock2.h WINSOCK_HEADER) +# if(NOT WINSOCK_HEADER) +# message(FATAL_ERROR "socket headers not found in system.") +# endif() +# endif() + +# check_include_file(unistd.h HAS_UNISTD) + +# If necessary, use the RELATIVE flag, otherwise each source file may be listed +# with full pathname. RELATIVE may makes it easier to extract an executable name +# automatically. +file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.c ) +# file( GLOB APP_SOURCES ${CMAKE_SOURCE_DIR}/*.c ) +# AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_SOURCES) +foreach( testsourcefile ${APP_SOURCES} ) + # I used a simple string replace, to cut off .cpp. + string( REPLACE ".c" "" testname ${testsourcefile} ) + add_executable( ${testname} ${testsourcefile} ) + + if(OpenMP_C_FOUND) + target_link_libraries(${testname} PRIVATE OpenMP::OpenMP_C) + endif() + if(MATH_LIBRARY) + target_link_libraries(${testname} PRIVATE ${MATH_LIBRARY}) + endif() + + if(HAS_UNISTD) + target_compile_definitions(${testname} PRIVATE HAS_UNISTD) + endif() + # if(ARPA_HEADERS) + # target_compile_definitions(${testname} PRIVATE ARPA_HEADERS) + # else() + # target_compile_definitions(${testname} PRIVATE WINSOCK_HEADER) + # endif() + + if(WIN32) + target_link_libraries(${testname} PRIVATE ws2_32) # link winsock library on windows + endif() + + install(TARGETS ${testname} DESTINATION "bin/client_server") + +endforeach( testsourcefile ${APP_SOURCES} ) diff --git a/client_server/client.c b/client_server/client.c index 2c45ae41..c34c93f7 100644 --- a/client_server/client.c +++ b/client_server/client.c @@ -1,14 +1,39 @@ -// Write CPP code here -#include -#include +/** + * @file + * @author [Nairit11](https://github.com/Nairit11) + * @author [Krishna Vedala](https://github.com/kvedala) + * @brief Client side implementation of Server-Client system. + * @see client_server/server.c + */ #include #include #include + +#ifdef _WIN32 // if compiling for Windows +#define _WINSOCK_DEPRECATED_NO_WARNINGS // will make the code invalid for next + // MSVC compiler versions +#include +#define bzero(b, len) \ + (memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ +#define read(a, b, c) recv(a, b, c, 0) /**< map BSD name to Winsock */ +#define write(a, b, c) send(a, b, c, 0) /**< map BSD name to Winsock */ +#define close closesocket /**< map BSD name to Winsock */ +#else // if not windows platform +#include +#include #include #include -#define MAX 80 -#define PORT 8080 -#define SA struct sockaddr +#endif + +#define MAX 80 /**< max. characters per message */ +#define PORT 8080 /**< port number to connect to */ +#define SA struct sockaddr /**< shortname for sockaddr */ + +/** + * Continuous loop to send and receive over the socket. + * Exits when "exit" is sent from commandline. + * @param sockfd socket handle number + */ void func(int sockfd) { char buff[MAX]; @@ -19,7 +44,9 @@ void func(int sockfd) printf("Enter the string : "); n = 0; while ((buff[n++] = getchar()) != '\n') + { ; + } write(sockfd, buff, sizeof(buff)); bzero(buff, sizeof(buff)); read(sockfd, buff, sizeof(buff)); @@ -32,12 +59,32 @@ void func(int sockfd) } } +#ifdef _WIN32 +/** Cleanup function will be automatically called on program exit */ +void cleanup() { WSACleanup(); } +#endif + +/** + * @brief Driver code + */ int main() { +#ifdef _WIN32 + // when using winsock2.h, startup required + WSADATA wsData; + if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0) + { + perror("WSA Startup error: \n"); + return 0; + } + + atexit(cleanup); // register at-exit function +#endif + int sockfd, connfd; struct sockaddr_in servaddr, cli; - // socket create and varification + // socket create and verification sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { @@ -45,7 +92,9 @@ int main() exit(0); } else + { printf("Socket successfully created..\n"); + } bzero(&servaddr, sizeof(servaddr)); // assign IP, PORT @@ -60,11 +109,14 @@ int main() exit(0); } else + { printf("connected to the server..\n"); + } // function for chat func(sockfd); // close the socket close(sockfd); + return 0; } diff --git a/client_server/server.c b/client_server/server.c index 26c6e1bb..e01af328 100644 --- a/client_server/server.c +++ b/client_server/server.c @@ -1,16 +1,49 @@ -#include -#include +/** + * @file + * @author [Nairit11](https://github.com/Nairit11) + * @author [Krishna Vedala](https://github.com/kvedala) + * @brief Server side implementation of Server-Client system. + * @see client_server/client.c + */ #include #include #include -#include -#include -#include -#define MAX 80 -#define PORT 8080 -#define SA struct sockaddr -// Function designed for chat between client and server. +// #ifdef HAS_UNISTD +// #include +// #endif + +#ifdef _WIN32 +#define _WINSOCK_DEPRECATED_NO_WARNINGS // will make the code invalid for next + // MSVC compiler versions +#include +#define bzero(b, len) \ + (memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ +#define read(a, b, c) recv(a, b, c, 0) /**< map BSD name to Winsock */ +#define write(a, b, c) send(a, b, c, 0) /**< map BSD name to Winsock */ +#define close closesocket /**< map BSD name to Winsock */ +#else +// if not windows platform +#include +#include +#include +#include +#endif + +#define MAX 80 /**< max. characters per message */ +#define PORT 8080 /**< port number to connect to */ +#define SA struct sockaddr /**< shortname for sockaddr */ + +#ifdef _WIN32 +/** Cleanup function will be automatically called on program exit */ +void cleanup() { WSACleanup(); } +#endif + +/** + * Continuous loop to send and receive over the socket. + * Exits when "exit" is sent from commandline. + * @param sockfd socket handle number + */ void func(int sockfd) { char buff[MAX]; @@ -28,7 +61,9 @@ void func(int sockfd) n = 0; // copy server message in the buffer while ((buff[n++] = getchar()) != '\n') + { ; + } // and send that buffer to client write(sockfd, buff, sizeof(buff)); @@ -42,21 +77,36 @@ void func(int sockfd) } } -// Driver function +/** Driver code */ int main() { - int sockfd, connfd, len; +#ifdef _WIN32 + // when using winsock2.h, startup required + WSADATA wsData; + if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0) + { + perror("WSA Startup error: \n"); + return 0; + } + + atexit(cleanup); // register at-exit function +#endif + + int sockfd, connfd; + unsigned int len; struct sockaddr_in servaddr, cli; // socket create and verification sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { - printf("socket creation failed...\n"); + perror("socket creation failed...\n"); exit(0); } else + { printf("Socket successfully created..\n"); + } bzero(&servaddr, sizeof(servaddr)); // assign IP, PORT @@ -67,35 +117,42 @@ int main() // Binding newly created socket to given IP and verification if ((bind(sockfd, (SA *)&servaddr, sizeof(servaddr))) != 0) { - printf("socket bind failed...\n"); + perror("socket bind failed...\n"); exit(0); } else + { printf("Socket successfully binded..\n"); + } // Now server is ready to listen and verification if ((listen(sockfd, 5)) != 0) { - printf("Listen failed...\n"); + perror("Listen failed...\n"); exit(0); } else + { printf("Server listening..\n"); + } len = sizeof(cli); // Accept the data packet from client and verification connfd = accept(sockfd, (SA *)&cli, &len); if (connfd < 0) { - printf("server acccept failed...\n"); + perror("server acccept failed...\n"); exit(0); } else + { printf("server acccept the client...\n"); + } // Function for chatting between client and server func(connfd); // After chatting close the socket close(sockfd); + return 0; } diff --git a/client_server/udp_client.c b/client_server/udp_client.c index 194847a6..2659e86b 100644 --- a/client_server/udp_client.c +++ b/client_server/udp_client.c @@ -1,19 +1,51 @@ -// Client side implementation of UDP client-server model +/** + * @file + * @author [TheShubham99](https://github.com/TheShubham99) + * @author [Krishna Vedala](https://github.com/kvedala) + * @brief Client side implementation of UDP client-server model + * @see client_server/udp_server.c + */ +#ifdef _WIN32 // if compiling for Windows +#define _WINSOCK_DEPRECATED_NO_WARNINGS // will make the code invalid for next + // MSVC compiler versions +#include +#define close closesocket /**< map BSD name to Winsock */ +#else // if not windows platform #include +#include #include -#include -#include -#include #include #include #include +#endif -#define PORT 8080 -#define MAXLINE 1024 +#include +#include +#include -// Driver code +#define PORT 8080 /**< port number to connect to */ +#define MAXLINE 1024 /**< maximum characters per line */ + +#ifdef _WIN32 +/** Cleanup function will be automatically called on program exit */ +void cleanup() { WSACleanup(); } +#endif + +/** Driver code */ int main() { +#ifdef _WIN32 + // when using winsock2.h, startup required + WSADATA wsData; + if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0) + { + perror("WSA Startup error: \n"); + return 0; + } + + atexit(cleanup); // register at-exit function +#endif + int sockfd; char buffer[MAXLINE]; char *hello = "Hello from client"; @@ -33,9 +65,10 @@ int main() servaddr.sin_port = htons(PORT); servaddr.sin_addr.s_addr = INADDR_ANY; - int n, len; + int n; + unsigned int len; - sendto(sockfd, (const char *)hello, strlen(hello), MSG_CONFIRM, + sendto(sockfd, (const char *)hello, strlen(hello), 0, (const struct sockaddr *)&servaddr, sizeof(servaddr)); printf("Hello message sent.\n"); diff --git a/client_server/udp_server.c b/client_server/udp_server.c index 2be350a2..7dbe323b 100644 --- a/client_server/udp_server.c +++ b/client_server/udp_server.c @@ -1,19 +1,51 @@ -// Server side implementation of UDP client-server model +/** + * @file + * @author [TheShubham99](https://github.com/TheShubham99) + * @author [Krishna Vedala](https://github.com/kvedala) + * @brief Server side implementation of UDP client-server model + * @see client_server/udp_client.c + */ +#ifdef _WIN32 // if compiling for Windows +#define _WINSOCK_DEPRECATED_NO_WARNINGS // will make the code invalid for next + // MSVC compiler versions +#define close closesocket /**< map BSD name to Winsock */ +#include +#else // if not windows platform #include +#include #include -#include -#include -#include #include #include #include +#endif -#define PORT 8080 -#define MAXLINE 1024 +#include +#include +#include -// Driver code +#define PORT 8080 /**< port number to connect to */ +#define MAXLINE 1024 /**< maximum characters per line */ + +#ifdef _WIN32 +/** Cleanup function will be automatically called on program exit */ +void cleanup() { WSACleanup(); } +#endif + +/** Driver code */ int main() { +#ifdef _WIN32 + // when using winsock2.h, startup required + WSADATA wsData; + if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0) + { + perror("WSA Startup error: \n"); + return 0; + } + + atexit(cleanup); // register at-exit function +#endif + int sockfd; char buffer[MAXLINE]; char *hello = "Hello from server"; @@ -41,14 +73,17 @@ int main() exit(EXIT_FAILURE); } - int len, n; + unsigned int len; + int n; n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, (struct sockaddr *)&cliaddr, &len); buffer[n] = '\0'; printf("Client : %s\n", buffer); - sendto(sockfd, (const char *)hello, strlen(hello), MSG_CONFIRM, + sendto(sockfd, (const char *)hello, strlen(hello), 0, (const struct sockaddr *)&cliaddr, len); printf("Hello message sent.\n"); + close(sockfd); + return 0; }