changeset 10:fd707ca47dd0

convert project to simple TCP server client app
author Dennis <dennisconcepcionmartin@gmail.com>
date Wed, 19 Jul 2023 18:40:47 +0100
parents ae1a84916424
children 827460e58a24
files CMakeLists.txt src/client/CMakeLists.txt src/client/main.c src/main.c src/server/CMakeLists.txt src/server/main.c
diffstat 6 files changed, 202 insertions(+), 149 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Tue Jul 18 20:06:11 2023 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-cmake_minimum_required(VERSION 3.1)
-project(hey 
-	VERSION 1.0 
-	LANGUAGES C
-)
-
-add_executable(hey src/main.c)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/client/CMakeLists.txt	Wed Jul 19 18:40:47 2023 +0100
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 3.1)
+project(hey-client 
+	VERSION 1.0 
+	LANGUAGES C
+)
+
+add_executable(hey_client main.c)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/client/main.c	Wed Jul 19 18:40:47 2023 +0100
@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#define MAX_MSG_SIZE 1000
+
+
+int main(int argc, char *argv[]) {
+	if (argc != 3) {
+		printf("Invalid arguments: hostname port\n");
+		exit(1);
+	}
+
+	char *hostname = argv[1];
+	char *port = argv[2];
+	struct addrinfo hints;
+	struct addrinfo *service_info;
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_flags = AI_PASSIVE;
+
+	if ((getaddrinfo(hostname, port, &hints, &service_info)) != 0) {
+		perror("getaddrinfo");
+		exit(1);
+	}
+
+	int clientfd = socket(service_info->ai_family, service_info->ai_socktype, service_info->ai_protocol);
+	if (clientfd == -1) {
+		perror("socket");
+	}
+
+	if (connect(clientfd, service_info->ai_addr, service_info->ai_addrlen) == -1) {
+		perror("connect");
+		exit(1);
+	}
+
+	freeaddrinfo(service_info);
+	printf("Connection established\n");
+
+	char msg[MAX_MSG_SIZE];
+	bool connected = true;
+
+	while (connected) {
+		printf("Enter command: ");
+		fgets(msg, MAX_MSG_SIZE, stdin);
+		msg[strcspn(msg, "\n")] = 0;
+
+		if (strcmp(msg, "exit") == 0) {
+			break;
+		}
+
+		ssize_t bytes_sent = send(clientfd, msg, strlen(msg), 0);
+		if (bytes_sent == -1) {
+			perror("send");
+			exit(1);
+		}
+
+		printf("%zd bytes sent\n", bytes_sent);
+		memset(&msg, 0, sizeof(msg));
+	}
+
+	close(clientfd);
+
+	return 0;
+}
--- a/src/main.c	Tue Jul 18 20:06:11 2023 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <time.h>
-#include <errno.h>
-
-
-int listenfd;
-
-void sigint_handler(int sig_num) {
-	printf("\nClosing socket\n");
-	close(listenfd);
-	exit(0);
-}
-
-void sigchld_handler(int s) {
-	int saved_errno = errno;
-	while(waitpid(-1, NULL, WNOHANG) > 0);
-	errno = saved_errno;
-}
-
-// Get IPv4 or IPv6
-struct IpPort {
-	char ipstr[INET6_ADDRSTRLEN];
-	unsigned short port;
-};
-
-struct IpPort get_ipport(struct sockaddr *sa) {
-	struct IpPort ipport;
-
-	if (sa->sa_family == AF_INET) {
-		struct sockaddr_in *ipv4 = (struct sockaddr_in *)sa;
-		inet_ntop(AF_INET, &(ipv4->sin_addr), ipport.ipstr, sizeof(ipport.ipstr));
-		ipport.port = ntohs(ipv4->sin_port);
-	} else {
-		struct sockaddr_in *ipv6 = (struct sockaddr_in *)sa;
-		inet_ntop(AF_INET, &(ipv6->sin_addr), ipport.ipstr, sizeof(ipport.ipstr));
-		ipport.port = ntohs(ipv6->sin_port);
-	}
-
-	return ipport;
-}
-
-int main() {
-	signal(SIGINT, sigint_handler);
-
-	struct addrinfo hints;
-	struct addrinfo *servinfo; 
-
-	memset(&hints, 0, sizeof hints); 	// Make sure the struct is empty
-	hints.ai_family = AF_UNSPEC;     	// Don't care IPv4 or IPv6
-	hints.ai_socktype = SOCK_STREAM; 	// TCP stream sockets
-	hints.ai_flags = AI_PASSIVE;     	// Fill in my IP for me
-
-	if ((getaddrinfo(NULL, "5050", &hints, &servinfo)) != 0) {
-		perror("getaddrinfo: ");
-		exit(1);
-	}
-
-	listenfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
-	if (listenfd == -1) {
-		perror("socket: ");
-		exit(1);
-	}
-
-	// Avoid "Address already in use"
-	int yes = 1;
-	if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
-		perror("setsockopt: \n");
-	}
-
-	if (bind(listenfd, servinfo->ai_addr, servinfo->ai_addrlen) == -1) {
-		perror("bind: ");
-		exit(1);
-	}
-
-	freeaddrinfo(servinfo);
-
-	if (listen(listenfd, 10) == -1) {
-		perror("listen: ");
-		exit(1);
-	}
-
-	// Kill zombie child processes
-	struct sigaction sig;
-	sig.sa_handler = sigchld_handler;
-	sigemptyset(&sig.sa_mask);
-	sig.sa_flags = SA_RESTART;
-	if (sigaction(SIGCHLD, &sig, NULL) == -1) {
-		perror("sigaction: \n");
-		exit(1);
-	}
-
-	struct IpPort server_ipport = get_ipport(servinfo->ai_addr);
-	printf("Server IP: %s\n", server_ipport.ipstr);
-	printf("Listening on port: %u\n", server_ipport.port);
-
-	char send_buffer[100];
-	struct sockaddr_storage clientinfo;
-	socklen_t clientinfo_size;
-	printf("Waiting for connections...\n");
-
-	while (1) {
-		int connfd = accept(listenfd, (struct sockaddr *)&clientinfo, &clientinfo_size);
-		if (connfd == -1) {
-			perror("accept: \n");
-			exit(1);
-		}
-
-		struct IpPort client_ipport = get_ipport((struct sockaddr *)&clientinfo);
-		printf("Client IP: %s\n", client_ipport.ipstr);
-		printf("Client port: %u\n", client_ipport.port);
-
-		int pid = fork();
-		if (pid == 0) {
-			// This is child
-			close(listenfd);
-			time_t now = time(NULL);
-			snprintf(send_buffer, sizeof(send_buffer), "Server time: %s\n", ctime(&now));
-
-			if (send(connfd, send_buffer, sizeof(send_buffer), 0) == -1) {
-				perror("send: \n");
-			}
-
-			close(connfd);
-			exit(0);
-		}
-
-		close(connfd);
-	}
-
-	return 0;
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/CMakeLists.txt	Wed Jul 19 18:40:47 2023 +0100
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 3.1)
+project(hey-server 
+	VERSION 1.0 
+	LANGUAGES C
+)
+
+add_executable(hey_server main.c)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/main.c	Wed Jul 19 18:40:47 2023 +0100
@@ -0,0 +1,117 @@
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <time.h>
+#include <errno.h>
+
+#define MAX_MSG_SIZE 1000
+
+
+// Get IPv4 or IPv6
+struct IpPort {
+	char ipstr[INET6_ADDRSTRLEN];
+	unsigned short port;
+};
+
+struct IpPort get_ipport(struct sockaddr *sa) {
+	struct IpPort ipport;
+
+	if (sa->sa_family == AF_INET) {
+		struct sockaddr_in *ipv4 = (struct sockaddr_in *)sa;
+		inet_ntop(AF_INET, &(ipv4->sin_addr), ipport.ipstr, sizeof(ipport.ipstr));
+		ipport.port = ntohs(ipv4->sin_port);
+	} else {
+		struct sockaddr_in *ipv6 = (struct sockaddr_in *)sa;
+		inet_ntop(AF_INET, &(ipv6->sin_addr), ipport.ipstr, sizeof(ipport.ipstr));
+		ipport.port = ntohs(ipv6->sin_port);
+	}
+
+	return ipport;
+}
+
+int main(int argc, char *argv[]) {
+	if (argc != 2) {
+		printf("Invalid arguments: port\n");
+		exit(1);
+	}
+
+	char *port = argv[1];
+	struct addrinfo hints;
+	struct addrinfo *service_info; 
+
+	memset(&hints, 0, sizeof hints); 	// Make sure the struct is empty
+	hints.ai_family = AF_UNSPEC;     	// Don't care IPv4 or IPv6
+	hints.ai_socktype = SOCK_STREAM; 	// TCP stream sockets
+	hints.ai_flags = AI_PASSIVE;     	// Fill in my IP for me
+
+	if ((getaddrinfo(NULL, port, &hints, &service_info)) != 0) {
+		perror("getaddrinfo: ");
+		exit(1);
+	}
+
+	int listenfd = socket(service_info->ai_family, service_info->ai_socktype, service_info->ai_protocol);
+	if (listenfd == -1) {
+		perror("socket: ");
+		exit(1);
+	}
+
+	if (bind(listenfd, service_info->ai_addr, service_info->ai_addrlen) == -1) {
+		perror("bind: ");
+		exit(1);
+	}
+
+
+	if (listen(listenfd, 10) == -1) {
+		perror("listen: ");
+		exit(1);
+	}
+
+	struct IpPort server_ipport = get_ipport(service_info->ai_addr);
+	printf("%s listening on port %u\n", server_ipport.ipstr, server_ipport.port);
+
+	freeaddrinfo(service_info);
+
+	struct sockaddr_storage clientinfo;
+	socklen_t clientinfo_size;
+	printf("Waiting for connections...\n");
+
+	int connfd = accept(listenfd, (struct sockaddr *)&clientinfo, &clientinfo_size);
+	if (connfd == -1) {
+		perror("accept: \n");
+		exit(1);
+	}
+
+	struct IpPort client_ipport = get_ipport((struct sockaddr *)&clientinfo);
+	printf("Connection from %s:%u\n", client_ipport.ipstr, client_ipport.port);
+
+	char msg[MAX_MSG_SIZE];
+
+	while (1) {
+		int recv_status = recv(connfd, &msg, sizeof(msg), 0);
+		if (recv_status == -1) {
+			perror("recv: %s\n");
+			exit(1);
+		} else if (recv_status == 0) {
+			printf("Client closed connection\n");
+			break;
+		} else {
+			printf("Client: %s\n", msg);
+		}
+
+		memset(&msg, 0, sizeof(msg));
+	}
+
+	close(connfd);
+	close(listenfd);
+
+	return 0;
+}
+