ecen5273

ECEN5273 Coursework
git clone https://git.pngu.org/ecen5273
Log | Files | Refs | README

uftp_client.c (6237B)


// File Transfer (Client)
// Jack Sangdahl
// 07 September 2024
#include <fcntl.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#define DATA_SIZE 1024

int main(int argc, char **argv) {
  if (argc != 3) {
    fprintf(stderr, "usage: %s <ip_addr> <port_num>\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;
}