// File Transfer (Client) // Jack Sangdahl // 07 September 2024 #include #include #include #include #include #include #include #include #define DATA_SIZE 1024 int main(int argc, char **argv) { if (argc != 3) { fprintf(stderr, "usage: %s \n", argv[0]); exit(EXIT_FAILURE); } char *hostname = argv[1]; int port = atoi(argv[2]), sock; if (port > 65535 || port < 5000) { fprintf(stderr, "%s: port must be in range 5000-65535\n", argv[0]); exit(EXIT_FAILURE); } if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { fprintf(stderr, "%s: error opening socket\n", argv[0]); exit(EXIT_FAILURE); } struct hostent *server = gethostbyname(hostname); if (!server) { fprintf(stderr, "%s: error determining server\n", argv[0]); exit(EXIT_FAILURE); } struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr.s_addr = INADDR_ANY; memcpy((char *)&server_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length); socklen_t server_size = sizeof(server_addr); char data[DATA_SIZE], command[DATA_SIZE], filename[DATA_SIZE]; while (1) { memset(data, 0, strlen(data)); printf("usage: get [filename] | put [filename] | delete [filename] | ls | " "exit\n"); fgets(data, DATA_SIZE, stdin); data[strcspn(data, "\n")] = 0; sscanf(data, "%s %s", command, filename); if (!strncmp(command, "get", 3)) { if (sendto(sock, data, strlen(data), 0, (struct sockaddr *)&server_addr, server_size) < 0) fprintf(stderr, "%s: error sending data to server\n", argv[0]); int rec_data; if (recvfrom(sock, &rec_data, sizeof(rec_data), 0, (struct sockaddr *)&server_addr, &server_size) < 0) fprintf(stderr, "%s: error receiving status from server\n", argv[0]); if (rec_data == -1) { fprintf(stderr, "error: file %s does not exist on server\n", filename); continue; } if (recvfrom(sock, data, sizeof(data), 0, (struct sockaddr *)&server_addr, &server_size) < 0) fprintf(stderr, "%s: error receiving file size\n", argv[0]); int file_size = atoi(data); printf("receiving file %s/%d bytes from server...\n", filename, file_size); int f = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); int bytes_transferred = 0; while (bytes_transferred < file_size) { memset(data, 0, sizeof(data)); ssize_t received = recvfrom(sock, data, sizeof(data), 0, (struct sockaddr *)&server_addr, &server_size); if (received < 0) fprintf(stderr, "%s: error receiving file data\n", argv[0]); write(f, data, received); bytes_transferred += received; printf("received %d/%d bytes\n", bytes_transferred, file_size); } close(f); printf("file transferred successfully.\n"); } else if (!strncmp(command, "put", 3)) { printf("sending file %s to server...\n", filename); int f = open(filename, O_RDONLY); if (f < 0) { fprintf(stderr, "error: file %s does not exist in directory\n", filename); continue; } if (sendto(sock, data, strlen(data), 0, (struct sockaddr *)&server_addr, server_size) < 0) fprintf(stderr, "%s: error sending data to server\n", argv[0]); off_t file_size = lseek(f, 0, SEEK_END); lseek(f, 0, SEEK_SET); char file_data[DATA_SIZE]; sprintf(file_data, "%ld", (long)file_size); if (sendto(sock, file_data, DATA_SIZE, 0, (struct sockaddr *)&server_addr, server_size) < 0) fprintf(stderr, "%s: error sending file size to server\n", argv[0]); memset(data, 0, sizeof(data)); ssize_t bytes_read; while ((bytes_read = read(f, file_data, sizeof(file_data))) > 0) { if (sendto(sock, file_data, bytes_read, 0, (struct sockaddr *)&server_addr, server_size) < 0) { fprintf(stderr, "%s: error sending data to server\n", argv[0]); break; } memset(file_data, 0, sizeof(file_data)); } if (bytes_read < 0) fprintf(stderr, "error reading file %s\n", filename); else printf("file %s transferred successfully\n", filename); close(f); } else if (!strncmp(command, "delete", 6)) { if (sendto(sock, data, strlen(data), 0, (struct sockaddr *)&server_addr, server_size) < 0) fprintf(stderr, "%s: error sending data to server\n", argv[0]); int rec_data; if (recvfrom(sock, &rec_data, sizeof(int), 0, (struct sockaddr *)&server_addr, &server_size) < 0) fprintf(stderr, "%s: error receiving data from server\n", argv[0]); switch (rec_data) { case 0: printf("file %s deleted successfully\n", filename); break; case 1: printf("file %s does not exist on server\n", filename); break; case 2: printf("error deleting file %s on server\n", filename); break; } } else if (!strncmp(command, "ls", 2)) { if (sendto(sock, data, strlen(data), 0, (struct sockaddr *)&server_addr, server_size) < 0) fprintf(stderr, "%s: error sending data to server\n", argv[0]); if (recvfrom(sock, data, sizeof(data), 0, (struct sockaddr *)&server_addr, &server_size) < 0) fprintf(stderr, "%s: error receiving data from server\n", argv[0]); printf("%s\n", data); } else if (!strncmp(command, "exit", 4)) { if (sendto(sock, data, strlen(data), 0, (struct sockaddr *)&server_addr, server_size) < 0) fprintf(stderr, "%s: error sending data to server\n", argv[0]); if (close(sock) < 0) fprintf(stderr, "%s: error closing socket\n", argv[0]); printf("%s: server connection closed\n", argv[0]); break; } else printf("invalid command!\n"); } return EXIT_SUCCESS; }