// File Transfer (Server) // Jack Sangdahl // 07 September 2024 #include #include #include #include #include #include #include #include #include #define DATA_SIZE 1024 int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "usage: %s \n", argv[0]); exit(EXIT_FAILURE); } int port = atoi(argv[1]), 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 sockaddr_in server_addr, client_addr; memset(&server_addr, 0, sizeof(server_addr)); memset(&client_addr, 0, sizeof(client_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons((short)port); if (bind(sock, (const struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { fprintf(stderr, "%s: error binding socket to port\n", argv[0]); exit(EXIT_FAILURE); } printf("ready to receive client connections\n"); socklen_t client_size = sizeof(client_addr); char data[DATA_SIZE], command[DATA_SIZE], filename[DATA_SIZE]; while (1) { memset(data, 0, strlen(data)); ssize_t n = recvfrom(sock, data, DATA_SIZE, 0, (struct sockaddr *)&client_addr, &client_size); if (n < 0) fprintf(stderr, "%s: error receiving datagram from client\n", argv[0]); struct hostent *host_info = gethostbyaddr((const char *)&client_addr.sin_addr.s_addr, sizeof(client_addr.sin_addr.s_addr), AF_INET); if (!host_info) fprintf(stderr, "%s: error determining host info\n", argv[0]); char *host_addr = inet_ntoa(client_addr.sin_addr); printf("%s: received datagram from %s (%s)\n", argv[0], host_info->h_name, host_addr); printf("received %d/%d bytes: %s\n", (int)strlen(data), (int)n, data); sscanf(data, "%s %s", command, filename); if (!strncmp(command, "get", 3)) { printf("sending file %s to client...\n", filename); int send_data, f = open(filename, O_RDONLY); if (f < 0) { send_data = -1; fprintf(stderr, "error: file %s does not exist in directory\n", filename); } else send_data = 1; if (sendto(sock, &send_data, sizeof(send_data), 0, (struct sockaddr *)&client_addr, client_size) < 0) { fprintf(stderr, "%s: error sending status to client\n", argv[0]); if (f >= 0) close(f); continue; } if (f < 0) continue; off_t file_size = lseek(f, 0, SEEK_END); if (file_size < 0) { fprintf(stderr, "error: determine file size of file %s\n", filename); close(f); continue; } lseek(f, 0, SEEK_SET); sprintf(data, "%ld", file_size); if (sendto(sock, data, strlen(data), 0, (struct sockaddr *)&client_addr, client_size) < 0) { fprintf(stderr, "%s: error sending file size to client\n", argv[0]); close(f); continue; } memset(data, 0, sizeof(data)); ssize_t bytes_read; while ((bytes_read = read(f, data, sizeof(data)))) { if (sendto(sock, data, bytes_read, 0, (struct sockaddr *)&client_addr, client_size) < 0) { fprintf(stderr, "%s: error sending data to client\n", argv[0]); break; } memset(data, 0, sizeof(data)); } if (bytes_read < 0) fprintf(stderr, "%s: error reading from file %s\n", argv[0], filename); close(f); } else if (!strncmp(command, "put", 3)) { printf("receiving file %s from client...\n", filename); if (recvfrom(sock, data, DATA_SIZE, 0, (struct sockaddr *)&client_addr, &client_size) < 0) fprintf(stderr, "%s: error receiving data from client\n", argv[0]); int file_size = atoi(data), f = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (f < 0) fprintf(stderr, "%s: error opening file %s\n", argv[0], filename); int bytes_transferred = 0; ssize_t bytes_received; while (bytes_transferred < file_size) { memset(data, 0, sizeof(data)); int transfer_size = (file_size - bytes_transferred < DATA_SIZE) ? (file_size - bytes_transferred) : DATA_SIZE; bytes_received = recvfrom(sock, data, transfer_size, 0, (struct sockaddr *)&client_addr, &client_size); if (bytes_received < 0) { fprintf(stderr, "%s: error receiving data from client\n", argv[0]); close(f); } if (write(f, data, bytes_received) != bytes_received) { fprintf(stderr, "%s: error writing data to file %s\n", argv[0], filename); close(f); } bytes_transferred += bytes_received; printf("received %d/%d bytes\n", bytes_transferred, file_size); } close(f); printf("file %s transferred successfully\n", filename); } else if (!strncmp(command, "delete", 6)) { int send_data, f = open(filename, O_RDWR); if (f < 0) { send_data = 1; if (sendto(sock, &send_data, sizeof(int), 0, (struct sockaddr *)&client_addr, client_size) < 0) fprintf(stderr, "%s: error sending data to client\n", argv[0]); } close(f); if (remove(filename) < 0) { send_data = 2; fprintf(stderr, "%s: error removing file %s\n", argv[0], filename); } else send_data = 0; if (sendto(sock, &send_data, sizeof(int), 0, (struct sockaddr *)&client_addr, client_size) < 0) fprintf(stderr, "%s: error sending data to client\n", argv[0]); } else if (!strncmp(command, "ls", 2)) { char send_data[DATA_SIZE] = {0}; DIR *d = opendir("."); int data_len = 0; struct dirent *curr; while ((curr = readdir(d))) { int name_len = strlen(curr->d_name); memcpy(send_data + data_len, curr->d_name, name_len); data_len += name_len; send_data[data_len] = '\n'; data_len++; } closedir(d); if (data_len) if (sendto(sock, send_data, strlen(send_data), 0, (struct sockaddr *)&client_addr, client_size) < 0) fprintf(stderr, "%s: error sending data to client\n", argv[0]); } else if (!strncmp(command, "exit", 4)) printf("received exit signal from client\n"); } return EXIT_SUCCESS; }