Il client invia solo un messaggio

di il
4 risposte

Il client invia solo un messaggio

Salve a tutti, ho un problema con l'invio dei messaggi tra Client e Server. Non capisco se il problema sia nella ricezione da parte del Server o l'invio da parte del Client. In pratica dovrei costruire un piccolo gioco senza grafica scritto sul Server (ovviamente), dove il Client si collega ed il suo unico compito è quello di inviare e ricevere messaggi.

IL PROBLEMA:
Step 1. dopo l'invio del primo messaggio il Server giustamente riceve il messaggio, lo rielabora ed in via la matrice (il gioco) aggiornata al Client che lo riceve correttamente e lo stampa correttamente;
Step 2. adesso rinvio il messaggio al Server ma quest'ultimo non lo riceve. il Client nuovamente stampa il vecchio contenuto e dopodiché mi chiede di inviare un terzo messaggio. ;
Step 3. Una volta inviato il terzo messaggio (il Server continua a non ricevere nulla) il Client interrompe la connessione (perché la interrompe se ho messo la funzione close() fuori dal ciclo infinito?).

Ecco il codice Server
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <errno.h>
#define MAX 10 //dimensione matrice
#define PORTA 1205 //porta sulla quale il server è in ascolto

void generazione(char m[][MAX]);
void stampa(char m[][MAX]);
void ostacoli(char m[][MAX]);
void personaggiopacchetto(char m[][MAX]);
int preso(char m[][MAX]);
int ipos(char m[][MAX]);
int jpos(char m[][MAX]);

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

	struct sockaddr_in indirizzoServer; //serve per mettersi in ascolto su una determinata porta
	struct sockaddr_in indirizzoClient; //serve per contenere le informzioni sulla connessione che mi arrivano dal client
	int socketDescriptor; //informazioni del server
	int clientConnectionDescriptor; //info sul client arrivate tramite l ACCEPT
	int i; //indice matrice
	int j; //indice matrice
	char m[MAX][MAX];//campo
	char scelta;
	int flag = 0; //flag controllo pacchetto
    int k=0; //indice buffer

	//creo il socket
	socketDescriptor=socket(AF_INET,SOCK_STREAM,0);//creo il socket(famiglia,tipo,protocollo(zero per protocollo migliore disp))
	if(socketDescriptor<0)perror("Errore creazione del socket!"),exit(1);

	indirizzoServer.sin_family=AF_INET;
	indirizzoServer.sin_addr.s_addr=htonl(INADDR_ANY);
	indirizzoServer.sin_port=htons(PORTA);

	//collego il socketDescriptor alla struttura indirizzoServer in cui ci sono i dati per comunicare
	if(bind(socketDescriptor,(struct sockaddr *)&indirizzoServer,sizeof(indirizzoServer))<0)
		perror("Errore BIND:"),exit(0);

	printf("In attesa di richieste da parte di un client...\n");

	//metto in ascolto il socket(sd,lunghezzaCoda);
	listen(socketDescriptor,1);
    

    //inizializzazione campo
    generazione(m);
	ostacoli(m);
	personaggiopacchetto(m);

    printf("Bisogna muoversi nel labirinto, prendere il pacchetto ed uscire per completare il gioco.\n\nLegenda: \nA-personaggio\nE-Uscita\nI-Spazio libero\nO-Ostacolo\nP-Pacchetto preso\n");
    char buffer[1000];
	while(1 && m[MAX-1][MAX-1] != 'P'){
		//accetto connessioni
		int lunghezzaClient;
		lunghezzaClient=sizeof(indirizzoClient);
		clientConnectionDescriptor=accept(socketDescriptor,(struct sockaddr *)&indirizzoClient,&lunghezzaClient);
		if(clientConnectionDescriptor<0){
			perror("Errore ACCEPT del server");
			exit(0);
		}

		//server concorrente
		pid_t pid;

		//creo un processo figlio
		if((pid=fork())<0){
			perror("Errore nella FORK:");
			exit(0);
		}else if(pid==0){//questo è quello che fa il processo figlio
			close(socketDescriptor); //lavora solo con clientConnectionDescriptor

			printf("*Nuova connessione dal client: %s\n",inet_ntoa(indirizzoClient.sin_addr));
			printf("In attesta di ricezione di un messaggio...\n");
            printf("\nUtilizzare WASD per muovere il personaggio all'interno del labirinto.\n");
            stampa(m);

			
			read(clientConnectionDescriptor,buffer,sizeof(buffer));

            printf("-[%s]Messaggio ricevuto: %s\n",inet_ntoa(indirizzoClient.sin_addr),buffer);
            
            scelta = buffer[k];
            printf("il buffer è %c\n", buffer[k]);
            

		switch(scelta){
			case 'A':
				i = ipos(m);
				j = jpos(m);
				flag = preso(m);
				if(m[i][j-1] != 'O' && m[i][j-1] != 'V'){
					if(flag == 0){
						m[i][j] = 'I';
						m[i][j-1] = 'A';
					}else{
						m[i][j] = 'I';
						m[i][j-1] = 'P'; 				
					}
					
				}else if(m[i][j-1] == 'V'){
					m[i][j] = 'I';
					m[i][j-1] = 'P';					
				}
				stampa(m);
            break;
            
            case 'D':
				i = ipos(m);
				j = jpos(m);
				flag = preso(m);
				if(m[i][j+1] != 'O' && m[i][j+1] != 'V'){
					if(flag == 0){
						m[i][j] = 'I';
						m[i][j+1] = 'A';
					}else{
						m[i][j] = 'I';
						m[i][j+1] = 'P'; 				
					}
				}else if(m[i][j+1] == 'V'){
					m[i][j] = 'I';
					m[i][j+1] = 'P';					
				}
				stampa(m);
            break;

	    case 'W':
				i = ipos(m);
				j = jpos(m);
				flag = preso(m);
				if(m[i-1][j] != 'O' && m[i-1][j] != 'V'){
					if(flag == 0){
						m[i][j] = 'I';
						m[i-1][j] = 'A';
					}else{
						m[i][j] = 'I';
						m[i-1][j] = 'P'; 				
					}
				}else if(m[i-1][j] == 'V'){
					m[i][j] = 'I';
					m[i-1][j] = 'P';					
				}
				stampa(m);
            break;

	    case 'S':
				i = ipos(m);
				j = jpos(m);
				flag = preso(m);
				if(m[i+1][j] != 'O' && m[i+1][j] != 'V'){
					if(flag == 0){
						m[i][j] = 'I';
						m[i+1][j] = 'A';
					}else{
						m[i][j] = 'I';
						m[i+1][j] = 'P'; 				
					}
				}else if(m[i+1][j] == 'V'){
					m[i][j] = 'I';
					m[i+1][j] = 'P';					
				}
				stampa(m);
            break;
				case 'a':
				i = ipos(m);
				j = jpos(m);
				flag = preso(m);
				if(m[i][j-1] != 'O' && m[i][j-1] != 'V'){
					if(flag == 0){
						m[i][j] = 'I';
						m[i][j-1] = 'A';
					}else{
						m[i][j] = 'I';
						m[i][j-1] = 'P'; 				
					}
					
				}else if(m[i][j-1] == 'V'){
					m[i][j] = 'I';
					m[i][j-1] = 'P';					
				}
				stampa(m);
            break;
            
            case 'd':
				i = ipos(m);
				j = jpos(m);
				flag = preso(m);
				if(m[i][j+1] != 'O' && m[i][j+1] != 'V'){
					if(flag == 0){
						m[i][j] = 'I';
						m[i][j+1] = 'A';
					}else{
						m[i][j] = 'I';
						m[i][j+1] = 'P'; 				
					}
				}else if(m[i][j+1] == 'V'){
					m[i][j] = 'I';
					m[i][j+1] = 'P';					
				}
				stampa(m);
            break;

	    case 'w':
				i = ipos(m);
				j = jpos(m);
				flag = preso(m);
				if(m[i-1][j] != 'O' && m[i-1][j] != 'V'){
					if(flag == 0){
						m[i][j] = 'I';
						m[i-1][j] = 'A';
					}else{
						m[i][j] = 'I';
						m[i-1][j] = 'P'; 				
					}
				}else if(m[i-1][j] == 'V'){
					m[i][j] = 'I';
					m[i-1][j] = 'P';					
				}
				stampa(m);
            break;

	    case 's':
				i = ipos(m);
				j = jpos(m);
				flag = preso(m);
				if(m[i+1][j] != 'O' && m[i+1][j] != 'V'){
					if(flag == 0){
						m[i][j] = 'I';
						m[i+1][j] = 'A';
					}else{
						m[i][j] = 'I';
						m[i+1][j] = 'P'; 				
					}
				}else if(m[i+1][j] == 'V'){
					m[i][j] = 'I';
					m[i+1][j] = 'P';					
				}
				stampa(m);
            break;
			
				}//fine switch

	    			
			printf("Attendo altre richieste...\n");

            write(clientConnectionDescriptor, m, 1000); //#######

            memset(buffer, 0, sizeof(buffer));

			exit(0);
		 }

		
    k++;
    close(clientConnectionDescriptor);
	}//fine while
    
	return 0;

}

void generazione(char m[][MAX]){

	int i;
	int j;

	for(i=0; i<MAX; i++){
		for(j=0; j<MAX; j++){
			m[i][j] = 'I';

			}
		}

}

void ostacoli(char m[][MAX]){
	int i;
	int j;
	int cont = 0;
	int casuale;

	casuale=rand()%20+11;
	while(cont<casuale){
		
		i=rand()%(MAX-1)+0;
		j=rand()%(MAX-1)+0;
	
		if(m[i][j] == 'I'){
			m[i][j] = 'O';
			cont++;
		}
	}

	m[MAX-1][MAX-1] = 'E';
}

void personaggiopacchetto(char m[][MAX]){
	
	int i;
	int j;	
	int cont = 0;

	while(cont<1){
		
		i=rand()%(MAX-1)+0;
		j=rand()%(MAX-1)+0;
	
		if(m[i][j] == 'I'){
			m[i][j] = 'A';
			cont++;
		}
	}

	cont = 0;
	while(cont<1){
		
		i=rand()%(MAX-1)+0;
		j=rand()%(MAX-1)+0;
	
		if(m[i][j] == 'I'){
			m[i][j] = 'V';
			cont++;
		}
	}
	
	
}

int ipos(char m[][MAX]){
	int i;
	int j;

	for(i=0; i<MAX; i++){
		for(j=0; i<MAX; j++){
			if(m[i][j] == 'A' || m[i][j] == 'P'){
				return i;			
			}

}
}
}


int jpos(char m[][MAX]){
	int i;
	int j;

	for(i=0; i<MAX; i++){
		for(j=0; i<MAX; j++){
			if(m[i][j] == 'A' || m[i][j] == 'P'){
				return j;			
			}

}
}
}

int preso(char m[][MAX]){

	int i;
	int j;

	for(i=0; i<MAX; i++){
		for(j=0; i<MAX; j++){
			if(m[i][j] == 'V'){
				return 0;			
			}else if(m[i][j] == 'P'){
				return 1;
			}
	
}
}
}
 
void stampa(char m[][MAX]){

	int i;
	int j;

	for(i=0; i<MAX; i++){
		for(j=0; j<MAX; j++){
			printf("%c   ", m[i][j]);

			}
			printf("\n");
		}

}
codice Client
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/types.h>
#include <string.h>

#define PORTA 1205

int main(void) {
    
	struct sockaddr_in serverDescriptor; //struct in cui inserisco le info del server a cui voglio connettermi
										 //poiche il client per connettersi deve conoscere ip e porta del server

    char buffer[1000];
	int socketClientDescriptor; //descrittore del socket locale del client
    
	//struttura alla quale mi connetto(il server cioè)
	serverDescriptor.sin_family=AF_INET;
	serverDescriptor.sin_port=htons(PORTA);
	inet_aton("192.168.***.***", &serverDescriptor.sin_addr);
    
	//creo un socket locale per il client
	socketClientDescriptor=socket(AF_INET,SOCK_STREAM,0);
	if(socketClientDescriptor<0)perror("Errore creazione client socket."),exit(0);
    
	//connetto il socket client all indirizzo ip del serve
	if( connect(socketClientDescriptor,(struct sockaddr *)&serverDescriptor,sizeof(serverDescriptor)) <0)
		perror("Errore durante la connessione al server."),exit(0);
	printf("!!!!!!Connesso al Server!!!!!!\n");
    while(1){
	char messaggio[100];
	printf("\nscrivi un messaggio da inviare al server: ");
	scanf("%s",messaggio);
    
    
	write(socketClientDescriptor,messaggio,sizeof(messaggio));
//----------------------------------------------------------
    int i;

    
	read(socketClientDescriptor,buffer,sizeof(buffer));
    printf("\n-[]Messaggio ricevuto: \n");
       
    for(i=0; i<100; i++){
        if(i % 10 == 0){
            printf("\n");     
        }else{
                printf("%c ", buffer[i]);
              }
    }

    memset(buffer, 0, sizeof(buffer));
    }//fine while
//----------------------------------------------------------
	close(socketClientDescriptor);


	return 0;
}

4 Risposte

  • Re: Il client invia solo un messaggio

    Dubito che qualcuno si metta a debuggare per te un programma così avanti nella realizzazione

    Ma hai provato la robustezza di una connessione singola 1 client - 1 server con ip fissi, inviando messaggi multipli dal client con dei semplici echo dal server, provando la caduta e il ripristino di una nuova connessione, prima di proseguire? Perché ora che ci hai messo pure dei fork di mezzo è dura...
  • Re: Il client invia solo un messaggio

    Quello che sto c endo è un progetto e nella traccia non è richiesto di testare la robustezza della rete. Comunque ho provato a collegarmi con più di un client allo stesso tempo ed il server reagisce ricapitolando tutto da capo e tenendo in considerazione solo l ultimo client che si è collegato.

    Comunque il problema rimane quello di riuscire ad inviare più di un messaggio con uno stesso client senza che si chiuda e che il server lo riceva
  • Re: Il client invia solo un messaggio

    Ma hai fatto un client che invia banalmente "ciao1" "ciao2" "ciao3" eccetera col server che ti risponde la stessa cosa? Se vuoi fare tutto insieme senza affrontare la complessità per gradi è normale che al primo errore ti blocchi... leva il fork e fai una prova accettando una connessione sola senza accettarne altre. Magari metti delle pause che l'invio/ricezione non è mica a tempo zero
  • Re: Il client invia solo un messaggio

    Ho risolto, semplicemente chiudevo i socket dalla apete del client prima di inviare altri messaggi
Devi accedere o registrarti per scrivere nel forum
4 risposte