Client


  Otteniene l' indirizzo di rete  del ST al quale si connette dal NS caldo. Analogamente al ST il C non conoscendo l' indirizzo di rete del NS caldo effettua un Bcast e come risposta ottiene la porta sulla quale il NS caldo risponde a richieste da parte dei C. Ottenuto l' indirizzo di un ST disponidile il C si connette direttamente e mantiene la connessione finchè l' utente non decide di uscire dal servizio, oppure in corrispondenza di un crash del ST. In questo caso il C in modo trasparente  si collega nuovamente al NS caldo (con un accesso diretto mediante cashing dell' indirizzo) per ottenere un ST che risolva il match precedentemente fallito. Si noti che in questa fase di recovery da crash del ST, occorre prendere in considerazione il caso in cui anche  il NS caldo che aveva risposto al Bcast sia caduto. In questo caso il riferimento diretto al NS caldo chiaramente fallisce ed il C prima di terminare definitivamente deve tentare nuovamente la ricerca di un NS caldo nella rete.

Descrizione sommaria del comportamento:


Codice

/* Codice del cliente. Per prima cosa si preoccopa di ottenere l' indirizzo di un st 
   dopodiche' interagisce con l' utente. Il programma ha un argomento che e' l' host 
   del NS:
                       
                  nome programma <host del NS>
                                                                                        */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#define BUFFERLEN 20 
#define BUFLEN 60 
#define PORTA_BCAST_NS 31000   /*porta Bcast di ricerca dei NS attivi*/
extern int make_socket(struct sockaddr_in*,int*,ushort,char,FILE*);
extern int connections(struct sockaddr_in*,int*,char*,ushort,char,FILE*);
extern void clear_screen(void);
extern int errno;
void handler();
void alrm_bcast();
void alrm_ns();
struct sockaddr_in baddr,     /*socket b_cast datagram*/ 
                   peeraddr;  /*socket peer datagram*/
                   
struct hostent *hp;
typedef struct {
               unsigned short porta_dg_cl;
               unsigned short porta_ls_st; 
               } MSG_NS;
MSG_NS*ptr_ns;
int s,sd,bsock,broken,brokensp;
char host[24],porta[10];
main(argc,argv)
int argc;
char* argv[];
{
typedef char TELEFONO[20];
typedef struct{
              int len;
              TELEFONO(*ptr_data)[];
              }MESSAGGIO;
MESSAGGIO mes_in;
int  i,flag,nf,lenght,len=sizeof(struct sockaddr_in);
char buf[BUFLEN],buffer[BUFFERLEN],item[BUFFERLEN];
char answer='s',*host_NS;
struct hostent *hp;
struct sockaddr_in nsaddr,  /*e' la socket di comunicazione col NS*/
                   staddr;  /*e' la socket di comunicazione col ST*/
                     
signal(SIGPIPE,handler);
ptr_ns=(MSG_NS*)malloc(sizeof(MSG_NS));
memset((MSG_NS*)ptr_ns,0,sizeof(MSG_NS));
memset(buf,0,BUFLEN);
B_CAST: signal(SIGALRM,alrm_bcast);
clear_screen();
fprintf(stderr,"\n\nattendere prego...");sleep(1);
/*invia un b_cast a significato implicito per ricercare nella rete un NS*/
if(connection(&baddr,&bsock,0,PORTA_BCAST_NS,'B',stderr))
   {fprintf(stderr,"errore nella creazione della socket B_CAST\n");
    exit();}
if(sendto(bsock,buffer,BUFFERLEN,0,(struct sockaddr *)&baddr,len)<0)
  {fprintf(stderr,"fallito l'invio del b_cast alla ricerca di un NS\n");
    exit();}
alarm(5); /*TIMEOUT di BROADCAST*/
if(recvfrom(bsock,ptr_ns,sizeof(MSG_NS),0,(struct sockaddr *)&peeraddr,&len)<0)
   {fprintf(stderr,"fallita la ricezione del b_cast alla ricerca di un NS\n");
    exit();}
alarm(0);
lenght=ntohl(peeraddr.sin_addr.s_addr);
hp=gethostbyaddr((char*)&lenght,sizeof(struct in_addr),peeraddr.sin_family); 
if(hp==NULL)
  host_NS=(char *)inet_ntoa(peeraddr.sin_addr);
else
  host_NS=hp->h_name;
fprintf(stderr,"Le informazioni pervenute dal NS sono le seguenti:\n\t\t\
host del NS: %s\n\t\tporta_dg_cl del NS: %d\n\t\tporta_ls_st del NS: %d\n\n",
	host_NS,(*ptr_ns).porta_dg_cl,(*ptr_ns).porta_ls_st);
fprintf(stderr,"\t\t\t\tPremi invio per continuare... ");getchar();
/*assegna la struttura d'indirizzo per la sock DG di comunicazione col NS*/
if(connection(&nsaddr,&sd,host_NS,(*ptr_ns).porta_dg_cl,'D',stderr))
   {fprintf(stderr,"errore nella creazione della connessione\n");
    exit;}
NS: if(broken) 
      {
      fprintf(stderr,"\n\n\n");
      fprintf(stderr,"%s %s: Errore di comunicazione.\n\t\tPremi invio per \
continuare... ",host,porta);getchar();
      }
    signal(SIGALRM,alrm_ns);
    /*invia al NS "una richiesta di ST" ed attende la risposta*/ 
    if(sendto(sd,buf,BUFLEN,0,(struct sockaddr *)&nsaddr,len)<0)
      {fprintf(stderr,"%s: sendto sock_dgram\n",strerror(errno));exit();}
    
    alarm(5); /*TIMEOUT di richiesta al NS*/
    if(recvfrom(sd,buf,BUFLEN,0,(struct sockaddr *)&nsaddr,&len)<0) goto B_CAST;
    alarm(0);
       
    i=0;  
    while(buf[i]==' ')i++;
    if(buf[i]=='*')
      {fprintf(stderr,"\nNessun ST registrato !.\n\n");
       close(bsock);close(sd);exit();}
    else
      {
      nf=sscanf(buf," %s %s ",host,porta);
      if(nf!=2) goto NS;
      }
    /*assegna la struttura d'indirizzo per la sock ST di connessione al ST*/
    if(connection(&staddr,&s,host,atoi(porta),'S',stderr))
      {fprintf(stderr,"errore nella creazione della connessione\n");goto NS;}
    do
     {
     clear_screen();
     fprintf(stderr,"\n\nConnessione al ST %s sulla porta %u\n",host,
	    ntohs(staddr.sin_port));
     if(!broken)
       {
       memset(item,0,BUFFERLEN);memset(buf,0,BUFLEN); 
       fprintf(stderr,"\nNome utente da ricercare  ");scanf("%s",item);
       getchar();
       }
     else
       fprintf(stderr,"\nNome utente da ricercare  %s\n",item);
     if(send(s,item,BUFFERLEN,0)!=BUFFERLEN)
       {broken=1;close(s);goto NS;}
     if(brokensp) goto NS;
     
     if(recv(s,&mes_in,sizeof(int),0)<1) 
       {broken=1;close(s);goto NS;}
     if(brokensp) goto NS;
     mes_in.ptr_data=(TELEFONO(*)[])malloc(sizeof(TELEFONO[mes_in.len]));
     i=recv(s,mes_in.ptr_data,sizeof(TELEFONO[mes_in.len]),0);
     fprintf(stderr,"\n\ti caratteri ricevuti del messaggio di risposta \
sono %d\n",i);
     if(mes_in.len==0)
       fprintf(stderr,"\tutente %s non presente nel db\n",item);
     else
       {
       fprintf(stderr,"\tl' utente %s ha i seguenti numeri telefonici:\n\n",
	       item);
       for(i=0;i<mes_in.len;i++)
	 fprintf(stderr,"\t%s\n",(*mes_in.ptr_data)[i]);
       }
     free(mes_in.ptr_data);
     fprintf(stderr,"\n\n\nVuoi continuare s/n ");
     answer=getchar();getchar();
     broken=brokensp=0;
     }
    while(answer=='s');
    fprintf(stderr,"Chiusura della connessione a %s sulla porta %u e \
terminazione\n",host,ntohs(staddr.sin_port));
    close(s); close(sd); close(bsock);
}
/*****************************************************************************/
/*              scadenza del TIMEOUT della richiesta Broad_Cast              */
/*****************************************************************************/
void alrm_bcast()
{
fprintf(stderr,"\n\nNessun NS attivo !!! \
Servizio non disponibile in rete.\n\n");
close(bsock);free(ptr_ns);exit(0);
}
/*****************************************************************************/
/*         scadenza del TIMEOUT della richiesta di ST disponibile al NS      */
/*****************************************************************************/
void alrm_ns()
{close(sd);broken=0;}
/*****************************************************************************/
/*         gestione del SIGPIPE in caso di crash della connessione al NS     */
/*****************************************************************************/
void handler() 
{brokensp=broken=1;close(s);}
/*NB: si possono verificare 2 tipi di errore:
      - di comunicasìzione dutrante la TX/RX
      - crash del ST (SIGPIPE)
  In entrambi i casi il CLIENT tenta di ottenere dal NS un nuovo ST al quale
  connettersi.
  broken indica il fallimento del supporto di comunicazione.
  brokensp indica un SIGPIPE.*/