Problema Client-Server

di il
3 risposte

Problema Client-Server

Salve a tutti, mi presento mi chiamo Francesco ed è la prima volta che scrivo su questo forum.Mi sono iscritto perchè sto avendo problemi relativi ad un programma in linguaggio c.
Passo alla spiegazione :
Il programma deve gestire ,tramite client-server, la gestione di una banca con tutte le operazioni descritte nel menù.
Una volta scritto e mandato in esecuzione il programma ho riscontrato 2 "difetti":

1) quando eseguo il client e passo il mio indirizzo ip della rete di casa il server che è in ascolto non trascrive il mio indirizzo esatto.Spiego meglio con un esempio: il mio indirizzo ip è 192.168.1.40 quindi quando eseguo ./client 192.168.1.40 il server come risposta mi dice che ha avuto una richiesta accettata dall'ip 0.0.0.0 sulla porta 0.

2) una volta scelto di terminare il client tramite l'azione del menù, il server rimane attivo.

Posto il codice di seguito

Client:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
//lista delle librerie

int            n,codice,y,sockfd;
char             recvline[1025] ;

typedef struct bancomat
    {
        char cognome[100];
        char nome[100];
        int codice_cliente;
        int denaro_cliente;
    }t_bancomat;

t_bancomat array_utenti[100];
t_bancomat ricevi;

int            sockfd, n,a,i=0,scelta;

char             recvline[1025] ;
char          buff[4096];

struct sockaddr_in servaddr;


//----------------------PROTOTIPI---------------------------------
int ricerca_cliente();
int aggiungi_denaro(t_bancomat array_utente[],int y);
int prelievo_denaro(t_bancomat array_utente[],int y);
void stampa();
void riempi_array(t_bancomat array_utenti[]);
int trasferimento_denaro(t_bancomat array_utente[]);
//----------------------------------------------------------------


int main(int argc, char **argv)
{
  
    if (argc != 2) 
    {
      fprintf(stderr,"usage: %s <IPaddress>\n",argv[0]);
      exit (1);
    }
    if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
    {
      fprintf(stderr,"socket error\n");
      exit (1);
    }
//crep òa socket
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(3666);
  if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) 
  {
    fprintf(stderr,"inet_pton error for %s\n", argv[1]);
    exit (1);
  }
    //do la definizione alla socket, la famiglia ip4, la porta associata e faccio la conversione 
    //della stringa che rappresenta l'indirizzo d rete
  if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) 
  {
    fprintf(stderr,"connect error\n");
    exit(1);
  }
//cerco di connettermi al server

	
  while (1)
     {
//stampo il menù	
	printf("Selezionare l'opzione desiderata\n");
	printf("1) Ricerca cliente\n");
	printf("2) Aggiungi denaro\n");
	printf("3) Preleva denaro\n");
	printf("4) Trasferisci denaro\n");
	printf("5) Chiudi sistema\n");
	scanf("%d",&scelta);
//leggo la scelta dell'utente e la invio al server tramite la write  
       snprintf(buff, sizeof(buff), "%d\r\n",scelta);
       if ( write(sockfd, buff, strlen(buff)) != strlen(buff)) 
       {
         perror("write");
         exit(1);
       }
// lo switch mi indirizza verso la mia scelta e chiama la procedura associata
      switch (scelta)
      {
 	case 1:
	i=ricerca_cliente();
	stampa();
	break;
	case 2:
	i=ricerca_cliente();
	aggiungi_denaro(array_utenti,i);
	stampa();
	break;
	case 3:
	i=ricerca_cliente();
	prelievo_denaro(array_utenti,i);
	stampa();
	break;
	case 4:
	i=ricerca_cliente();
	y=trasferimento_denaro(array_utenti);
	stampa();
	break;
	case 5:
	exit(1);
	break;
	default:
	printf("errore \n");
	break;
      }

    }
 
  exit(0);
}


int ricerca_cliente()
{
int i=0;
    printf("Inserire il codice utente da ricercare \n");
    scanf("%d",&codice);
    snprintf(buff, sizeof(buff), "%d\r\n",codice);
    if ( write(sockfd, buff, strlen(buff)) != strlen(buff)) 
    {
      perror("write");
      exit(1);
    }
//questa funzione chiede il codice utente da ricercare e lo invia al server tramite una write
}

int aggiungi_denaro(t_bancomat array_utente[],int y)
{
	int i=0,aggiungi;
	printf("quanto vuoi depositare? \n");
	scanf("%d",&aggiungi);
	snprintf(buff, sizeof(buff), "%d\r\n",aggiungi);
         if ( write(sockfd, buff, strlen(buff)) != strlen(buff)) 
          {
           perror("write");
           exit(1);
          }
//questa funzione chiede all'utente quanto vuole depositare e tramite una write lo invia al server
}

int prelievo_denaro(t_bancomat array_utente[],int y)
{
	int preleva;
	
	printf("quanto vuoi prelevare? \n");
	scanf("%d",&preleva);
	snprintf(buff, sizeof(buff), "%d\r\n",preleva);
         if ( write(sockfd, buff, strlen(buff)) != strlen(buff)) 
          {
           perror("write");
           exit(1);
          }
//questa funzione chiede all'utente quanto vuole prelevare e tramite una write lo invia al server
}
void stampa()
{
    read(sockfd, &ricevi, sizeof(ricevi));
    printf("cognome %s \n", ricevi.cognome);
    printf("nome %s \n", ricevi.nome);
    printf("denaro cliente €%d \n", ricevi.denaro_cliente);
    printf("codice cliente n°%d \n", ricevi.codice_cliente);
//questa procedura riceve tramite la read i dati del cliente e li stampa con una printf
}


int trasferimento_denaro(t_bancomat array_utente[])
{
 int i_mittente,somma,i_destinatario;

	printf("A chi vuoi destinare il bonifico= ");
	i_destinatario=ricerca_cliente(array_utente);
	printf("quanto vuoi trasferire? ");
	scanf("%d",&somma);
        snprintf(buff, sizeof(buff), "%d\r\n",somma);
         if ( write(sockfd, buff, strlen(buff)) != strlen(buff)) 
          {
           perror("write");
           exit(1);
          }
	return(i_destinatario);
//questa funzione è per il trasferimento d denaro chiede per prima cosa i codici degli utenti, poi chiede la somma da trasferire e invia tutto al 
//server che gestità i dati ricevuti
}
Server:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
//lista di librerie 
 

typedef struct bancomat
    {
        char cognome[100];
        char nome[100];
        int codice_cliente;
        int denaro_cliente;
    }t_bancomat; // struct per la gestione dei dati

t_bancomat prova;

int socket_list, connfd,a,n,socket_conn;

struct sockaddr_in servaddr,client;

//char  buffer[4096];
char  recvline[1025];

time_t atime;
pid_t pid;
int n,codice,i=1,y;
int logging =0;
int one=1;


//----------------------PROTOTIPI---------------------------------
int ricerca_cliente(t_bancomat array_utenti[]);
int aggiungi_denaro(t_bancomat array_utente[],int y);
int prelievo_denaro(t_bancomat array_utente[],int y);
void stampa(t_bancomat array_utente[], int y);
void riempi_array(t_bancomat array_utenti[]);
int trasferimento_denaro(t_bancomat array_utente[]);
//----------------------------------------------------------------

int main(int argc, char **argv)
 {

  int scelta,z=0;
	 char  buffer[4096];
  t_bancomat array_utenti[100];

    if (( socket_list = socket(AF_INET, SOCK_STREAM, 0) ) < 0 ) //creo la socket altrimenti stampa l'errore
      {
         perror("Creazione socket fallita!\n");
         exit(1);
      }
    
	riempi_array(array_utenti); //carico i dati sull'array
    servaddr.sin_family           = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port          = htons(3666);
    //do la definizione alla socket, la famiglia ip4, la porta associata e faccio la conversione 
    //della stringa che rappresenta l'indirizzo d rete
    
	 if(setsockopt(socket_list, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))<0) 
    {
     printf("ERROR_SETSOCKOPT\n");
     exit(1);
    }//setsockopt è una chiamata per la gestione degli errori
    
    printf("Setsockopt riuscita\n");
    
	 if ( bind(socket_list, (struct sockaddr *) &servaddr,sizeof(servaddr)) < 0 )
    {
     perror("ERROR_BIND\n");
     exit(1);
    }printf("Bind riuscita\n");
    // la bind assegna un'indirizzo
    
	 if ( listen(socket_list, 1024) < 0 )
    {
     perror("ERROR_LISTEN\n");
     exit(1);
    }printf("In ascolto...\n");
    // la listen si mette in ascolto d eventuali connessioni da parte di un client
   
	 while(1)
    {
     if ( ( socket_conn = accept(socket_list, (struct sockaddr *) NULL, NULL) ) < 0 )
     {
      perror("ERROR_ACCEPT");
      exit(1);
     }else {
		 printf("Connessione Accettata\n");
		 logging=1;
	 }

	 
   //questa funzione accetta la connessione da parte di un client, notare che c'è un while prima
   //in modo da poter gestire + connessioni contemporaneamente grazie anche alla funzione che segue
  
	if((pid= fork())<0)
	{
		perror (" FORK ERROR");
		exit ( -1);
	}

	if(pid==0)
	{ // la fork() crea un processo figlio identico a quello del padre
	  close (socket_list);
	  
      if(logging)
      {
        inet_ntop(AF_INET,&client.sin_addr,buffer,sizeof(buffer));
		  printf("richiesta dell' host %s con porta %d\n",buffer,ntohs(client.sin_port));
		
      }
      
	 while (1)
       {
         n = read(socket_conn, recvline, 1024);
    	 recvline[n] = 0;
   		 if (fputs(recvline, stdout) == EOF)
   		  {
            fprintf(stderr,"fputs error\n");
            exit(1);
          }
	    scelta=atoi(recvline);
        // legge con una read la scelta fatta dal client e mandatagli tramite la socket
        
		   
		   
		switch (scelta)
         {
       //lo switch gestisce le varie scelte in ogni caso fa prima la ricerca del client
            case 1:
            i=ricerca_cliente(array_utenti);
            stampa(array_utenti,i);
            break;
            case 2:
            i=ricerca_cliente(array_utenti);
            aggiungi_denaro(array_utenti,i);
            stampa(array_utenti,i);
            break;
            case 3:
            i=ricerca_cliente(array_utenti);
            prelievo_denaro(array_utenti,i);
            stampa(array_utenti,i);
            break;
            case 4:
            i=ricerca_cliente(array_utenti);
            y=trasferimento_denaro(array_utenti);
            stampa(array_utenti,y);
            break;
            case 5:
			printf("Connessione Terminata..\n");
            exit(1);
            break;
            default:
            printf("errore \n");
            exit(1);
            break;
            z=z++;

         }
        }
 close(socket_conn);
    }
close(socket_conn); 
//chiude la connessione
}



 exit(0);
}


void riempi_array(t_bancomat array_utenti[])
{
//funzione che riempe l'array di dati
    strcpy(array_utenti[1].cognome, "Napolitano");
    strcpy(array_utenti[1].nome, "Gennaro");
    array_utenti[1].codice_cliente=1001;
    array_utenti[1].denaro_cliente=5000;

    strcpy(array_utenti[2].cognome,"Rossi");
    strcpy(array_utenti[2].nome,"Mario");
    array_utenti[2].codice_cliente=1002;
    array_utenti[2].denaro_cliente=3700;

    strcpy(array_utenti[3].cognome,"Bianco");
    strcpy(array_utenti[3].nome,"Luigi");
    array_utenti[3].codice_cliente=1003;
    array_utenti[3].denaro_cliente=6600;

    strcpy(array_utenti[4].cognome,"Verdi");
    strcpy(array_utenti[4].nome,"Antonio");
    array_utenti[4].codice_cliente=1004;
    array_utenti[4].denaro_cliente=900;
}


int ricerca_cliente(t_bancomat array_utenti[])
{
//funzione che ricerca il cliente dopo aver letto tramite la read il codice inviato dal client e restituisce l'indice dell'utente ricercato
int i=0,n,codice;
    printf("Inserire il codice utente da ricercare \n");

 	n = read(socket_conn, recvline, 1024);
	recvline[n] = 0;
 	 if (fputs(recvline, stdout) == EOF) {
 	   fprintf(stderr,"fputs error\n");
      	   exit(1);
    	}
    codice=atoi(recvline);
    printf("codice %d\n",codice);

    while(array_utenti[i].codice_cliente!=codice)
    {
        i++;
    }
    return(i);
}

int aggiungi_denaro(t_bancomat array_utente[],int y)
{
//funzione che "aggiunge denaro", dopo aver ricevuto il codice dell'utente del quale bisogna aggiungere denaro, legge tramite 
//socket la somma da aggiungere
	int aggiungi,n;

	n = read(socket_conn, recvline, 1024);
	recvline[n] = 0;
 	 if (fputs(recvline, stdout) == EOF) {
 	   fprintf(stderr,"fputs error\n");
      	   exit(1);
    	}
        aggiungi=atoi(recvline);
	printf("prima %d\n",array_utente[y].denaro_cliente);
	array_utente[y].denaro_cliente=array_utente[y].denaro_cliente+aggiungi;
	printf("dopo %d\n",array_utente[y].denaro_cliente);
}

int prelievo_denaro(t_bancomat array_utente[],int y)
{
//funzione che "preleva denaro", dopo aver ricevuto il codice dell'utente del quale bisogna prelevare denaro, legge tramite 
//socket la somma da prelevare
	int preleva,n;

	n = read(socket_conn, recvline, 1024);
	recvline[n] = 0;
 	 if (fputs(recvline, stdout) == EOF) {
 	   fprintf(stderr,"fputs error\n");
      	   exit(1);
    	}
        preleva=atoi(recvline);
	printf("prima %d\n",array_utente[y].denaro_cliente);
	array_utente[y].denaro_cliente=array_utente[y].denaro_cliente-preleva;
	printf("dopo %d\n",array_utente[y].denaro_cliente);
}
void stampa(t_bancomat array_utente[], int y)
{
//procedura che invia al client la struct contenente i dati del cliente della banca
prova=array_utente[y];
write(socket_conn,&prova,sizeof(prova));
}


int trasferimento_denaro(t_bancomat array_utente[])
{
//funzione che permette il trasferimento di denaro tra un'utente e un'altro. prima riceve i due codici degli utenti e poi trasferisce 
//la somma da un'utente ad un'altro
 int i_mittente,somma,i_destinatario,n;

	i_destinatario=ricerca_cliente(array_utente);

        n = read(socket_conn, recvline, 1024);
	recvline[n] = 0;
 	 if (fputs(recvline, stdout) == EOF) {
 	   fprintf(stderr,"fputs error\n");
      	   exit(1);
    	}
        somma=atoi(recvline);

	printf("codice destinatario %d",i_destinatario);
        array_utente[i].denaro_cliente=array_utente[i].denaro_cliente-somma;
	array_utente[i_destinatario].denaro_cliente=array_utente[i_destinatario].denaro_cliente+somma;
	return(i_destinatario);
}

I problemi sono nel server penso per quanto riguarda il primo problema, credo nella chiamata
 inet_ntop(AF_INET,&client.sin_addr,buffer,sizeof(buffer));
		  printf("richiesta dell' host %s con porta %d\n",buffer,ntohs(client.sin_port));

Vi ringrazio in anticipo per l'aiuto!

3 Risposte

  • Re: Problema Client-Server

    Ciao steinar7,

    premetto che non l'ho compilato e non ho visto eventuali irregolarità, ma per il primo punto nel codice server non vai a leggerti la struttura definita sockaddr_in client

    $man 3p accept
    ...
    int accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len);
    ...
    address
    Either a null pointer, or a pointer to a sockaddr structure where the address of the connecting socket shall be returned.

    address_len
    Points to a socklen_t structure which on input specifies the length of the supplied sockaddr structure, and on output specifies the length of the stored address.
    ....
    Il secondo punto è che dovresti usare la famiglia recv* invece della read

    $man 3p recv


    ...
    ssize_t recv(int sockfd, void *buf, size_t len, int flags);

    ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

    ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

    ...
    ...
    RETURN VALUE
    These calls return the number of bytes received, or -1 if an error occurred. The return value will be 0 when the peer has performed an orderly shutdown.
    ...
  • Re: Problema Client-Server

    Perdona se ti rispondo così in ritardo...ti ringrazio veramente tanto!! ho capito l'errore...BIG UP!!
  • Re: Problema Client-Server

Devi accedere o registrarti per scrivere nel forum
3 risposte