/* Prezentowany poniżej program-klient służy do pobierania zawartości       */
/* pliku o wskazanej nazwie z serwera o wskazanym adresie internetowym.     */
/* W odpowiedzi na żądanie serwer przesyła jednorazowo całą zawartość pliku */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define SERVER_PORT 12345	/* wartość wybrana arbitralnie, musi być jednakowa */
                                /* dla klienta i serwera */
#define BUF_SIZE 4096		/* wielkosć porcji przesyłania danych */

int main(int argc, char **argv)
{
  int c, s, bytes;
  char buf[BUF_SIZE];			/* bufor dla przesyłanej zawartości */
  struct hostent *h;			/* zawiera informację o serwerze */
  struct sockaddr_in channel;		/* zawiera adres IP serwera */

  if (argc != 3) fatal("Wywołanie: client <nazwa serwera> <nazwa pliku>");
  h = gethostbyname(argv[1]);		/* uzyskiwanie adresu IP serwera */
                                        /* na podstawie jego nazwy      */
  if (!h) fatal("nie można uzyskać adresu IP serwera");

  s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (s < 0) fatal("nie można utworzyć gniazda");
  memset(&channel, 0, sizeof(channel));
  channel.sin_family= AF_INET;
  memcpy(&channel.sin_addr.s_addr, h->h_addr, h->h_length);
  channel.sin_port= htons(SERVER_PORT);
  c = connect(s, (struct sockaddr *) &channel, sizeof(channel));
  if (c < 0) fatal("nie powiodło się wywołanie funkcji connect");

  /* Połączenie zostalo nazwiązane */
  /* Przesłanie nazwy pliku zakończonej zerowym ogranicznikiem */
  write(s, argv[2], strlen(argv[2])+1);

  /* odczytywanie zawartości pliku i wypisywanie jej na standardowe wyjście */
  while (1) {
        bytes = read(s, buf, BUF_SIZE);	/* czytaj porcję z gniazda */
        if (bytes <= 0) exit(0);	        /* sprawdź, czy nie koniec pliku */
        write(1, buf, bytes);		        /* wypisz porcję na standardowe wyjście */
  }
}

fatal(char *string)
{
  printf("%s\n", string);
  exit(1);
}

