Il client invia solo un messaggio

di Anonimizzato26166 il
4 risposte
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

  • 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...
  • 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
  • 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
  • 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