Stranica kolegija | Termin konzultacija




    Vjezbe 1 & 2



    Vjezbe 3-6

    • download putty

    • Kako koristiti putty

    • Zadatak 1:Pomocu naredbe finger ispisite popis svih korisnika koji su ulogirani na racunalo za kojim sjedite u praktikumu. Iz praktikuma je dozvoljen ssh samo na ostala racunala u lokalnoj mrezi i na racunalo student. Odabrerite proizvoljno racunalo iz lokalne mreze i pogledajte tko je sve logiran na njemu. Provjerite i tko je sve logiran na racunalu student.

    • Interne naredbe unutar (s)ftp klijenta:
      ? ili help: popis svih internih naredbi
      ls : ispis svih datoteka u trenutnom direktoriju na udaljenom racunalu
      lls :ispis svih datoteka u trenutnom direktoriju na lokalnom racunalu
      pwd : ime trenutnog direktorija na udaljenom racunalu
      lpwd : ime trenutnog direktorija na lokalnom racunalu
      cd imeDirektorija : promjena direktorija na udaljenom racunalu
      lcd imeDirektorija : promjena direktorija na lokalnom racunalu

    • download sftp

    • Zadatak 2: Na udaljenom racunalu (asistent ce vam reci ip-adresu, te korisnicko ime i password) dostupna je ftp usluga. Prekopirajte datoteku slika.jpg sa udaljenog na svoje racunalo. Pogledajte pristiglu datoteku.
      Na svom racunalu napravite tekst datoteku koja se zove login.txt (login zamijenite svojim korisnickim imenom), te ju prenesite na udaljeno racunalo. Provjerite je li datoteka stigla.

    • Potrebni headeri:
      #include <sys/socket.h>
      #include <sys/types.h>
      #include <netdb.h>
      #include <netinet/in.h>
      #include <unistd.h>

    • Binarni IP zapis zivi u ovoj strukturi:
      struct in_addr 
      {
         unsigned long s_addr;
      };

    • struktura hostent:
      struct hostent {
         char *h_name;
         char **h_aliases;
         int h_addrtype;
         int h_length;
         char **h_addr_list;
      };
      #define h_addr h_addr_list[0]

      h_name : sluzbeni host-name racunala
      h_aliases : polje alternativnih host-name-ova racunala (zadnji je NULL)
      h_addrtype : tip adrese, kod nas uvijek AF_INET
      h_length : duljina adrese u byteovima, kod nas uvijek 4
      h_addr_list : polje binarnih zapisa IP-adresa racunala (zadnja je NULL)
      h_addr : prvi binarni zapis u gornjem polju

    • Primjer za pretvaranje hostname<->binarni IP:
      struct hostent *hostInfo;
      hostInfo = gethostbyname( "www.yahoo.com" );
      if( hostInfo == NULL ) herror( "gethostbyname" );
      
      printf( "Sluzbeni host-name: %s\n", hostInfo->h_name );
      struct in_addr binarniIP=*((struct in_addr *)hostInfo->h_addr);
      char *dekadskiIP = inet_ntoa( binarniIP );

    • Primjer za pretvaranje binarni IP <->hostname:
      struct hostent *hostInfo;
      struct in_addr binarniIP; 
      inet_aton( "161.53.8.14", &binarniIP ); // error-check...
      hostInfo = gethostbyaddr( 
        (const char *)&binarniIP, sizeof( binarniIP ), AF_INET );
      if( hostInfo == NULL ) herror( "gethostbyaddr" );
      
      printf( "Sluzbeni host-name: %s\n", hostInfo->h_name );
      char *dekadskiIP = inet_ntoa( 
         *((struct in_addr *)hostInfo->h_addr) );

    • Zadatak 3: Napisite program koji se ponasa slicno mreznom alatu nslookup. Program sa komandne linije treba dobiti host-name nekog racunala. Program treba ispisati sve host-name-ove i sve IP-adrese tog racunala. Ako host-name nije bio dobar, program treba ispisati poruku o greski.

    • Primjer stvaranja socketa:
      int mojSocket = socket( PF_INET, SOCK_STREAM, 0 );
      if( mojSocket == -1 )
         perror( "socket" );

    • Struktura sockaddr_in:
      struct sockaddr_in {
         short sin_family;
         unsigned short sin_port;
         struct in_addr sin_addr;
         char sin_zero[8];
      };

      sin_family : vrsta adrese, za nas AF_INET (komunikacija internetom)
      sin_port : port na serveru na koji se spajamo (broj izmedju 0 i 65535)
      sin_addr : binarna IP-adresa servera
      sin_zero : polje ciji se svi elementi uvijek postave na 0

    • Primjer upotrebe connect:
      char dekadskiIP[] = "12.34.56.7";
      struct sockaddr_in adresaServera;
      
      adresaServera.sin_family = AF_INET;
      adresaServera.sin_port = htons( 13 );
      
      if( inet_aton( dekadskiIP, &adresaServera.sin_addr ) == 0 )
         printf( "%s nije dobra adresa!\n", dekadskiIP );
      
      memset( adresaServera.sin_zero, '\0', 8 );
      
      if( connect( mojSocket, 
                   (struct sockaddr *) &adresaServera,
                   sizeof( adresaServera ) ) == -1 )
         perror( "connect" );   

    • Objasnjenja za htons i memset:
      Svaki broj (2 ili 4 byte-ni) koji se salje preko mreze treba imati poredak byte-ova u tzv. Network orderu, koji se moze razlikovati od poretka byte-ove koristenog na lokalnom racunalu (tzv. Host order).
      Zbog toga postoje funkcije konverzije:
      short htons( short x ) : prima x u Host orderu, vraca u Network
      long htonl( long x ) : prima x u Host orderu, vraca u Network
      short ntohs( short x ) :prima x u Network orderu, vraca u Host
      long ntohl( long x ) : prima x u Network orderu, vraca u Host
      Funkcija inet_aton vraca binarnu IP-adresu u Network orderu, pa tu ne treba konverzija.

      Funkcija memset() kopira c (kovertiran na unsigned char) u svaki od prvih n byteova objekta na koji pokazuje s. Sintaksa:
      
          #include 
      
          void *memset(void *s, int c, size_t n);
      
      Funkcija memset() vraca s; nema nikakve posebne vrijednosti koju treba vratiti u slucaju greske.

    • Funkcija recv
      ssize_t recv( int sock, void *buffer, size_t duljinaBuffera, int opcije );

      sock uticnica stvorena sa sock i povezana sa connect
      buffer adresa(najcese polje znakova; moze biti i npr. adresa samo jednog int-a) na koju spremamo podatke koji dolaze sa servera
      duljinaBuffera = sizeof( buffer ). Funkcija prima maksimalno onoliko podataka kolika je duljina buffera
      opcije = 0 za sve nase potrebe
      Povratna vrijednost:
      0, ako je druga strana prekinula konekciju, -1, ako je doslo do pogreske (pozovi perror za detalje), inace, broj byte-ova koji je stigao od udaljenog racunala

    • recv za daytime:
      char buffer[100];
      int primljeno = 0; // koliko smo byte-ova ukupno primili
      int novoprimljeno; // koliko je primljeno u zadnjem recv
      while( 1 )
      {
      novoprimljeno = recv(
      mojSocket,
      buffer + primljeno,
      sizeof( buffer ) primljeno - 1, // zbog '\0'
      0 );
      if( novoprimljeno == -1 ) { perror( "recv" ); exit(0); }
      else if( novoprimljeno == 0 ) break;
      else primljeno += novoprimljeno;
      }
      buffer[primljeno] = '\0'; printf( "%s", buffer );

    • Zatvaranje socketa
      if( close( mojSocket ) == -1 )
            perror( "close" );

    • Zadatak 4: Spojite sve navedene primjere u funkcionalni program - daytime klijent.

    • Funkcija bind
      int bind( int sock, struct sockaddr *servAddr, socklen_t addrlen );

      sock : uticnica koju smo napravili sa socket( )
      servAddr : napunjena sockaddr_in structura (koristimo cast!), cuva podatke o serveru. Ako ne znamo serverovu (tj. vlastitu) IP-adresu, ili znamo da imamo samo jednu IP-adresu, mozemo postaviti servAddr.s_addr = INADDR_ANY; i to polje ce automatski biti ispunjeno na ispravan nacin.
      addrlen = sizeof( servAddr );
      povratna vrijednost = -1 ako je doslo do greske (perror za detalje), 0 inace

    • Primjer bind
      struct sockaddr_in mojaAdresa;
      mojaAdresa.sin_family = AF_INET;
      mojaAdresa.sin_port = htons( 54321 );
      mojaAdresa.sin_addr.s_addr = INADDR_ANY;
      memset( mojaAdresa.sin_zero, '\0', 8 );
      if( bind( listenerSocket,(struct sockaddr *) &mojaAdresa,sizeof( mojaAdresa ) ) == -1 )
              perror( "bind" );

    • Funkcija listen
      int listen( int sock, int maxKonekcija );
      

      sock : uticnica koju smo napravili sa socket( ) i dali joj port pomocu bind( )
      maxKonekcija : koliko maksimalno klijenata odjednom moze cekati na uslugu servera. Ostali ce pri pokusaju connect-a dobiti pogresku "Connection refused"
      povratna vrijednost = -1 ako je doslo do greske (perror za detalje), 0 inace

    • Primjer listen
      if( listen( listenerSocket, 10 ) == -1 )  perror( "listen" );
      

    • Primjer accept
      struct sockaddr_in klijentAdresa;
      unsigned int lenAddr = sizeof( klijentAdresa );
      int commSocket = accept( listenerSocket, (struct sockaddr *) &klijentAdresa, &lenAddr );
      if( commSocket == -1 ) perror( "accept" );
      
      //ispis: 
      char *dekadskiIP = inet_ntoa( klijentAdresa.sin_addr );
      printf( "Prihvatio konekciju od %s\n", dekadskiIP );
      

    • Funkcija send
      ssize_t send( int sock, const void *buffer, size_t duljinaBuffera, int opcije );
      sock : uticnica preko koje se odvija komunikacija ( u nasem primjeru je to ona stvorena funkcijom accept )
      buffer :adresa (najcesce polje znakova; moze biti i npr. adresa samo jednog int-a) na koju spremamo podatke koji dolaze sa servera
      duljinaBuffera = sizeof( buffer )
      opcije = 0 za sve nase potrebe
      Povratna vrijednost:
      0, ako je druga strana prekinula konekciju, -1, ako je doslo do pogreske (pozovi perror za detalje), inace, broj byte-ova koji je stigao od udaljenog racunala

    • Primjer send
      #include<time.h>
      
      time_t trenutnoVrijeme;     //time_t je tip za vrijeme u sekundama
      time( &trenutnoVrijeme );   // prototip: time_t time(time_t *tloc); vraca vrijeme u sek, 
      //tloc je pointer na mjesto gdje se takodjer sprema to vrijeme
      
      char buffer[100];
      sprintf( buffer, "%s", ctime( &trenutnoVrijeme ) ); // prototip char *ctime(const time_t *clock); 
      //pretvara vrijeme u date and time string
      
      int trebaPoslati = strlen( buffer );
      int poslano = 0; // broj do sada poslanih byte-ova
      int poslanoZadnje; // koliko je poslano u zadnjem send
      
      while( poslano != trebaPoslati )
      {
         poslanoZadnje = send( commSocket, buffer + poslano, trebaPoslati - poslano, 0 );
         if( poslanoZadnje == -1 ) perror( "send" );
         else poslano += poslanoZadnje;
      }
      

    • Zadatak 5: Spojite sve primjere u jedan program - daytime server, koji moze posluzivati vise klijenata (vazno uociti: jednog za drugim, a ne vise istovremeno). Promijenite daytime-klijenta iz Zadatka 4 tako da se moze spajati na port 54321. Spojite se promijenjenim klijentom na nas daytime server.

    • Zadatak 6 (DZ):Napisite echo-klijent. Echo-klijent treba: spojiti se na racunalo student na port 7 (tamo se nalazi echo-server), u petlji ucitavati rijeci sve dok se ne ucita rijec kraj, svaku ucitanu rijec poslati serveru te procitati serverov odgovor i ispisati ga na ekran.
      Sto radi echo-server? Napisite ga (sami odaberite port komunikacije).
      Prilagodite svoj echo-klijent tako da sa komandne linije dobiva IP-adresu i port echo-servera na kojeg se treba spojiti. Testirajte sa echo-serverom na studentu i onim kojeg ste sami napisali.

    • Zadatak7 (DZ): Napisite primitivni web-browser koji ce moci prikazati jednu web-stranicu u tekstualnom modu. Za web se koristi tzv. http-protokol. Web-browser (tj. http-klijent) treba: spojiti se na proizvoljni host-name kojeg dobijete iz komandne linije na port 80 (tamo se uvijek nalaze http-serveri), poslati serveru poruku "GET / HTTP/1.0\n\n", ucitavati odgovor servera i ispisati ga na ekran. Modificirajte program tako da ispisujete samo ono sto se nalazi izmedju <body> i </body> (ili <BODY> i </BODY>). Nemojte ispisivati nista sto se nalazi izmedju znakova "<" i ">" (niti njih).


    • Zadatak 8: Potrebno je napraviti mreznu aplikaciju koja ce sluziti za vodjenje jednostavnog skladista. Server vodi evidenciju o kolicini pojedinog artikla koji se cuva na skladistu. Klijent moze: dovoziti nove artikle na skladiste, odvoziti postojece artikle sa skladista, provjeravati koliko pojedinih artikala ima na skladistu. Server treba davati klijentu odgovor o eventualnom neuspjesnom izvrsavanju zahtjeva.

    • Vrste poruka:
      STAVI artikl kolicina : klijent salje serveru informaciju o tome da zeli na skladiste dovesti izvjesnu kolicinu artikla
      UZMI artikl kolicina : klijent salje serveru informaciju o tome da zeli sa skladista odvesti izvjesnu kolicinu artikla
      KOLIKO artikl : klijent salje serveru poruku da zeli doznati koliko se artikla nalazi na skladistu
      KOLIKO_R artikl kolicina : server salje klijentu poruku sa kolicinom artikla koja se nalazi u skladistu
      BOK : klijent salje serveru znak za prekid komunikacije. Nakon toga server prekida komunikaciju.
      Dobro je i da server uvijek, na svaku klijentovu poruku(zahtjev) posalje nekakav odgovor, pa imamo jos jedan tip:
      ODGOVOR poruka : poruka je string koji je jednak "OK" ako je zahtjev uspjesno obradjen, inace sadrzi opis greske

    • Primjer komunikacije:
      client: [7,STAVI] DASKE 3
      server: [2,ODGOVOR] OK
      client: [7,UZMI] DASKE 15
      server: [27,ODGOVOR] Nema dovoljno artikla DASKE
      client: [3,KOLIKO] DASKE
      server: [2,ODGOVOR] OK
      server: [7,KOLIKO_R] DASKE 3

    • Sto klijent radi:
      prima IP-adresu i port servera npr. putem komandne linije,
      "iscrta" meni klijentu; u meniju nudi :
      ispis koliko ima nekog artikla na skladistu,
      stavljanje neke kolicine artikla u skladiste,
      micanje neke kolicine artikla sa skladista,
      izlaz iz programa (prekid komunikacije)

    • Sto server radi :
      ima polje u kojem je popis imena i kolicina pojedinog artikla,
      kada klijent posalje zahtjev za stavljanje novog artikla na skladiste, server prodje kroz polje i ako u njemu postoji taj artikl, poveca njegovu kolicinu, a ako nema tog artikla onda ga doda na kraj polja,
      ako klijent trazi artikl kojeg nema u skladistu ili ga nema dovoljno, server salje poruku o gresci i ne provodi klijentovu naredbu

    • Zadatak 9: Dodajte u prethodni program (zadatak 8) mogucnost da klijent dobije popis svih artikala koji se nalaze u skladistu.

    • Jos jedan slozeniji primjer i njegova rjesenja mozete pogledati na: primjer (autor Z.Bujanovic), header, pomocni program, klijent, server.

    • vise o mreznom programiranju

    • Puni tekst vjezbi nalazi se na sluzbenoj web stranici pod "materijali".

    Vjezbe 7 i 8




    Vjezbe 9-11


    Vjezbe 12

    
    
ak.god. 2007/08