Guardie e Ladri client/server

di il
22 risposte

Guardie e Ladri client/server

Salve,
devo scrivere un applicazione client/server in C che permetta di giocare a guardie e ladri via rete. In sostanza avevo pensato di demandare la visualizzazione dell'area di gioco (la posizione della guardia e del ladro) ai due client, mentre il server si limita a creare una partita per ogni coppia di client che si connettono e a gestirla (invia i dati sulle posizioni e quando scade il tempo o la guardia prende il ladro, comunica i risultati).

Io per ora ho realizzato una versione "base", che dovrebbe aspettare che si connettano due client per creare la partita, e una volta creata continuare a inviare e ricevere le coordinate finchè la guardia non prende il ladro. Il problema è che non riesco a distinguere i due client (nello specifico quando si connette il secondo client i messaggi arrivano tutti a lui e il primo client viene ignorato). Potete darmi una mano? Il codice è questo qui

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/times.h>


#define SERVER_PORT 1025
#define MAX_CONN 10


struct pos {      	//rappresentazione delle coordinate del personaggio
	char c;
	int x;
	int y;
};

int main (unsigned argc, char **argv) {
	int sock, client_len, fdguardia, fdladro;
	int waiting=0;
	char prev='l';
	struct sockaddr_in server, guardia, ladro;
	if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		perror("chiamata alla system call socket fallita");
		exit(1);
	}
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = htonl(INADDR_ANY);
	server.sin_port = htons(SERVER_PORT);
	if (bind(sock, (struct sockaddr *)&server, sizeof server) == -1) {
		perror("chiamata alla system call bind fallita");
		exit(2);
	}
	listen(sock, MAX_CONN);
	/* gestione delle connessioni dei clienti */
	while (1) {
		if (prev == 'l'){
			client_len = sizeof (guardia);
			if ((fdguardia = accept(sock, (struct sockaddr *)&guardia, &client_len)) < 0) { 
				perror("accepting connection");
				exit(3);
			}
			prev = 'g';
		}
		else{
			client_len = sizeof (ladro);
			if ((fdguardia = accept(sock, (struct sockaddr *)&ladro, &client_len)) < 0) { 
				perror("accepting connection");
				exit(3);
			}
			prev = 'l';
		}		
		waiting++;
		if (waiting >1){
			send(fdguardia, "Avvio partita\n", 14, 0);
			send(fdladro, "Avvio partita\n", 14, 0);
			waiting = waiting - 2;	
			//startgame(fdguardia, fdladro);
			prova (fdguardia, fdladro);
	
		} else 
			send(fdguardia, "Ricerca giocatori in corso...\n", 31, 0);			
	}
}


void startgame (int guardia, int ladro){
	struct pos pguardia, pladro;
	do{	
		recv(guardia, &pguardia, sizeof(pguardia), 0);  //ricevi la posizione della guardia
		recv(ladro, &pladro, sizeof(pladro), 0);        //ricevi la posizione del ladro
		send(guardia, &pladro, sizeof(pladro),0);	//invia alla guardia la posizione del ladro
		send(ladro, &pguardia, sizeof(pguardia),0);	//invia al ladro la posizione della guardia
	}while (collision(pguardia, pladro) != 0);		//controlla se coincidono
	send(guardia, "Hai vinto\n", 10, 0);			//la guardia ha preso il ladro, comunica la vittoria
	send(ladro, "Hai perso\n", 10, 0);			//comunica la sconfitta al ladro
	close (guardia);
	close(ladro);
}

int collision (struct pos a, struct pos b){			// verifica se le due posizioni coincidono
	if((a.x == b.x) && (a.y == b.y)) 
		return 1;
	else 
		return 0;
}

void prova (int guardia, int ladro){
	int i;
	for (i=0; i<10; i++){
		send (guardia, i, sizeof(i),0);
		send (ladro, i, sizeof(i),0);	
	}
	close (guardia);
	close(ladro);
}
Non avendo ancora scritto il client le prove le ho fatte con telnet

22 Risposte

  • Re: Guardie e Ladri client/server

    Ciao phatejoker,

    hai fatto un errore simile a quello di Berny88 nel thread poco più sotto.
    Se non avviene una connessione al socket con il relativo descrittore bisogna usare recvfrom e sendto:
    
    ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                            struct sockaddr *src_addr, socklen_t *addrlen);
    ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                          const struct sockaddr *dest_addr, socklen_t addrlen);
    
    
    Il manuale lo spiega chiaramente:
    ...
    The send() call may be used only when the socket is in a connected state (so that the intended recipient is known).
    ...
    ...
    If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET) socket, the arguments dest_addr and addrlen are ignored (and the error EISCONN may be returned when they are not NULL and 0), and the error ENOT-CONN is returned when the socket was not actually connected. Otherwise, the address of the target is given by dest_addr with addrlen specifying its size.
    ...
  • Re: Guardie e Ladri client/server

    Ho trovato l'errore, praticamente alla seconda connessione facevo ritornare il valore della accept sempre a fdguardia invece che a fdladro... adesso funziona tutto perfettamente.
  • Re: Guardie e Ladri client/server

    ixamit ha scritto:


    ...
    Se non avviene una connessione al socket con il relativo descrittore bisogna usare recvfrom e sendto:
    ...
    Bhe, cannando il descrittore...

    Non ho guardato bene anche perché a me compila con una spataffiata di warning:
    
    max@studio:~> gcc a.c -Wall
    a.c:24:1: warning: first argument of ‘main’ should be ‘int’
    a.c: In function ‘main’:
    a.c:33:7: warning: implicit declaration of function ‘exit’
    a.c:33:7: warning: incompatible implicit declaration of built-in function ‘exit’
    a.c:41:7: warning: incompatible implicit declaration of built-in function ‘exit’
    a.c:51:31: warning: pointer targets in passing argument 3 of ‘accept’ differ in signedness
    /usr/include/sys/socket.h:214:12: note: expected ‘socklen_t * __restrict__’ but argument is of type ‘int *’
    a.c:54:8: warning: incompatible implicit declaration of built-in function ‘exit’
    a.c:62:31: warning: pointer targets in passing argument 3 of ‘accept’ differ in signedness
    /usr/include/sys/socket.h:214:12: note: expected ‘socklen_t * __restrict__’ but argument is of type ‘int *’
    a.c:65:8: warning: incompatible implicit declaration of built-in function ‘exit’
    a.c:76:4: warning: implicit declaration of function ‘prova’
    a.c: In function ‘startgame’:
    a.c:96:3: warning: implicit declaration of function ‘collision’
    a.c: At top level:
    a.c:113:1: warning: conflicting types for ‘prova’
    a.c:76:4: note: previous implicit declaration of ‘prova’ was here
    a.c: In function ‘prova’:
    a.c:118:7: warning: passing argument 2 of ‘send’ makes pointer from integer without a cast
    /usr/include/sys/socket.h:141:16: note: expected ‘const void *’ but argument is of type ‘int’
    a.c:119:7: warning: passing argument 2 of ‘send’ makes pointer from integer without a cast
    /usr/include/sys/socket.h:141:16: note: expected ‘const void *’ but argument is of type ‘int’
    max@studio:~> 
    
  • Re: Guardie e Ladri client/server

    L'avevo notato ma mi ero concentrato sull'altro problema. Ho fatto alcune modifiche ma non riesco proprio a capire come eliminare quei warning (anche negli esempi che ho trovato in giro l'utilizzo delle socket è fatto così...). Come posso fare?
    #include <sys/types.h>
    
    #include <sys/socket.h>
    
    #include <netinet/in.h>
    
    #include <arpa/inet.h>
    
    #include <netdb.h>
    
    #include <stdio.h>
    
    #include <unistd.h>
    
    #include <ctype.h>
    
    #include <sys/times.h>
    
    
    
    
    
    #define SERVER_PORT 1025
    
    #define MAX_CONN 10
    
    
    
    
    
    struct pos {      	//rappresentazione delle coordinate del personaggio
    
    	char c;
    
    	int x;
    
    	int y;
    
    };
    
    
    
    int main (unsigned argc, char **argv) {
    
    	int sock, client_len, fdguardia, fdladro;
    
    	int waiting=0;
    
    	char prev='l';
    
    	struct sockaddr_in server, guardia, ladro;
    
    	if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    
    		perror("chiamata alla system call socket fallita");
    
    		exit(1);
    
    	}
    
    	server.sin_family = AF_INET;
    
    	server.sin_addr.s_addr = htonl(INADDR_ANY);
    
    	server.sin_port = htons(SERVER_PORT);
    
    	if (bind(sock, (struct sockaddr *)&server, sizeof server) == -1) {
    
    		perror("chiamata alla system call bind fallita");
    
    		exit(2);
    
    	}
    
    	listen(sock, MAX_CONN);
    
    	/* gestione delle connessioni dei clienti */
    
    	printf("Server avviato correttamente\n");
    
    	while (1) {
    
    		if (prev == 'l'){
    
    			client_len = sizeof (guardia);
    
    			if ((fdguardia = accept(sock, (struct sockaddr *)&guardia, &client_len)) < 0) { 
    
    				perror("accepting connection");
    
    				exit(3);
    
    			}
    
    			prev = 'g';
    
    		}
    
    		else{
    
    			client_len = sizeof (ladro);
    
    			if ((fdladro = accept(sock, (struct sockaddr *)&ladro, &client_len)) < 0) { 
    
    				perror("accepting connection");
    
    				exit(3);
    
    			}
    
    			prev = 'l';
    
    		}		
    
    		waiting++;
    
    		printf("ricevuta una connessione\n");
    
    		if (waiting >1){
    
    			send(fdguardia, "Avvio partita\n", 14, 0);
    
    			send(fdladro, "Avvio partita\n", 14, 0);
    
    			waiting = waiting - 2;	
    
    			//startgame(fdguardia, fdladro);
    
    			prova (fdguardia, fdladro);
    
    	
    
    		} else 
    
    			send(fdguardia, "Ricerca giocatori in corso...\n", 31, 0);			
    
    	}
    
    	printf("Shutdown server\n");
    
    	close (sock);
    
    }
    
    
    
    
    
    void startgame (int guardia, int ladro){
    
    	struct pos pguardia, pladro;
    
    	do{	
    
    		recv(guardia, &pguardia, sizeof(pguardia), 0);  //ricevi la posizione della guardia
    
    		recv(ladro, &pladro, sizeof(pladro), 0);        //ricevi la posizione del ladro
    
    		send(guardia, &pladro, sizeof(pladro),0);	//invia alla guardia la posizione del ladro
    
    		send(ladro, &pguardia, sizeof(pguardia),0);	//invia al ladro la posizione della guardia
    
    	}while (collision(pguardia, pladro) != 0);		//controlla se coincidono
    
    	send(guardia, "Hai vinto\n", 10, 0);			//la guardia ha preso il ladro, comunica la vittoria
    
    	send(ladro, "Hai perso\n", 10, 0);			//comunica la sconfitta al ladro
    
    	close (guardia);
    
    	close(ladro);
    
    }
    
    
    
    int collision (struct pos a, struct pos b){			// verifica se le due posizioni coincidono
    
    	if((a.x == b.x) && (a.y == b.y)) 
    
    		return 1;
    
    	else 
    
    		return 0;
    
    }
    
    
    
    void prova (int guardia, int ladro){
    
    	int i;
    
    	send (guardia, "Tu sei la guardia\n", 18,0);
    
    	send (ladro, "Tu sei il ladro\n", 16,0);
    
    	for (i=0; i<10; i++){
    
    		send (guardia, "guardia\t", 8,0);
    
    		send (ladro, "ladro\t", 6,0);	
    
    	}
    
    	send (guardia, "\nAdesso chiudo la connessione\n", 30,0);
    
    	send (ladro, "\nAdesso chiudo la connessione\n", 30,0);
    
    	close (guardia);
    
    	close(ladro);
    
    }
  • Re: Guardie e Ladri client/server

    Mi sembrano autoesplicativi...
    comincia con includere gli header per exit, main e' definito diversamente, i prototypes per prova e quell'altra sono da mettere o controllare.
    controlla come sono i prototypes per send e accept

    correggi e manda un dump degli warning rimanenti
  • Re: Guardie e Ladri client/server

    Ti ho corretto gli warning, fai un diff per vedere i punti:
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <unistd.h>
    #include <ctype.h>
    #include <sys/times.h>
    
    #define SERVER_PORT 1025
    #define MAX_CONN 10
    
    struct pos {			//rappresentazione delle coordinate del personaggio
    	char c;
    	int x;
    	int y;
    };
    
    void prova(int guardia, int ladro)
    {
      int i;
      for (i = 0; i < 10; i++) {
        send(guardia, "Hello ", 6, 0);
        send(ladro, "World ", 6, 0);
      }
      close(guardia);
      close(ladro);
    }
    int collision(struct pos a, struct pos b)
    {       // verifica se le due posizioni coincidono
      if ((a.x == b.x) && (a.y == b.y))
        return 1;
      else
        return 0;
    }
    
    
    int main(int argc, char **argv)
    {
    	int sock, client_len, fdguardia, fdladro;
    	int waiting = 0;
    	char prev = 'l';
    	struct sockaddr_in server, guardia, ladro;
    	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    		perror("chiamata alla system call socket fallita");
    		exit(1);
    	}
    	server.sin_family = AF_INET;
    	server.sin_addr.s_addr = htonl(INADDR_ANY);
    	server.sin_port = htons(SERVER_PORT);
    	if (bind(sock, (struct sockaddr *)&server, sizeof server) == -1) {
    		perror("chiamata alla system call bind fallita");
    		exit(2);
    	}
    	listen(sock, MAX_CONN);
    	/* gestione delle connessioni dei clienti */
    	while (1) {
    		if (prev == 'l') {
    			client_len = sizeof(guardia);
    			if ((fdguardia =
    			     accept(sock, NULL,
    				    0)) < 0) {
    				perror("accepting connection");
    				exit(3);
    			}
    			prev = 'g';
    		} else {
    			client_len = sizeof(ladro);
    			if ((fdladro =
    			     accept(sock, NULL,
    				    0)) < 0) {
    				perror("accepting connection");
    				exit(3);
    			}
    			prev = 'l';
    		}
    		waiting++;
    		if (waiting > 1) {
    			send(fdguardia, "Avvio partita\n", 14, 0);
    			send(fdladro, "Avvio partita\n", 14, 0);
    			waiting = waiting - 2;
    			//startgame(fdguardia, fdladro);
    			prova(fdguardia, fdladro);
    
    		} else
    			send(fdguardia, "Ricerca giocatori in corso...\n", 31,
    			     0);
    	}
    }
    
    void startgame(int guardia, int ladro)
    {
    	struct pos pguardia, pladro;
    	do {
    		recv(guardia, &pguardia, sizeof(pguardia), 0);	//ricevi la posizione della guardia
    		recv(ladro, &pladro, sizeof(pladro), 0);	//ricevi la posizione del ladro
    		send(guardia, &pladro, sizeof(pladro), 0);	//invia alla guardia la posizione del ladro
    		send(ladro, &pguardia, sizeof(pguardia), 0);	//invia al ladro la posizione della guardia
    	}
    	while (collision(pguardia, pladro) != 0);	//controlla se coincidono
    	send(guardia, "Hai vinto\n", 10, 0);	//la guardia ha preso il ladro, comunica la vittoria
    	send(ladro, "Hai perso\n", 10, 0);	//comunica la sconfitta al ladro
    	close(guardia);
    	close(ladro);
    }
    
    
    Ora prosegui!
  • Re: Guardie e Ladri client/server

    Sono riuscito a correggerli prima che rispondessi, grazie comunque!

    Sono andato avanti ma adesso ho un altro problema: il server pare funzionare bene (aspetta le due connessioni ed invia quello che deve inviare), ma il client che ho scritto non funziona... In pratica riceve il primo messaggio di ricerca altri giocatori ma poi va in ciclo infinito (mentre dovrebbe uscire dal ciclo dove si blocca non appena riceve il messaggio "START"). Posto i relativi codici.

    Server:
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <ctype.h>
    #include <sys/times.h>
    
    
    #define SERVER_PORT 1025
    #define MAX_CONN 10
    
    void startgame (int guardia, int ladro);
    void prova (int guardia, int ladro);
    
    
    struct pos {      	//rappresentazione delle coordinate del personaggio
    	char c;
    	int x;
    	int y;
    };
    
    int main () {
    	int sock, client_len, fdguardia, fdladro;
    	int waiting=0;
    	char prev='l';
    	struct sockaddr_in server, guardia, ladro;
    	if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    		perror("chiamata alla system call socket fallita");
    		exit(1);
    	}
    	server.sin_family = AF_INET;
    	server.sin_addr.s_addr = htonl(INADDR_ANY);
    	server.sin_port = htons(SERVER_PORT);
    	if (bind(sock, (struct sockaddr *)&server, sizeof server) == -1) {
    		perror("chiamata alla system call bind fallita");
    		exit(2);
    	}
    	listen(sock, MAX_CONN);
    	/* gestione delle connessioni dei clienti */
    	printf("Server avviato correttamente\n");
    	while (1) {
    		if (prev == 'l'){
    			client_len = sizeof (guardia);
    			if ((fdguardia = accept(sock, (struct sockaddr *)&guardia, &client_len)) < 0) { 
    				perror("accepting connection");
    				exit(3);
    			}
    			prev = 'g';
    		}
    		else{
    			client_len = sizeof (ladro);
    			if ((fdladro = accept(sock, (struct sockaddr *)&ladro, &client_len)) < 0) { 
    				perror("accepting connection");
    				exit(3);
    			}
    			prev = 'l';
    		}		
    		waiting++;
    		printf("ricevuta una connessione\n");
    		if (waiting >1){
    			waiting = waiting - 2;	
    			//startgame(fdguardia, fdladro);
    			prova (fdguardia, fdladro);
    	
    		} else 
    			send(fdguardia, "Ricerca giocatori in corso...\n", 31, 0);			
    	}
    	printf("Shutdown server\n");
    	close (sock);
    }
    
    
    void startgame (int guardia, int ladro){
    	struct pos pguardia, pladro;
    	send(guardia, "START", 5, 0);
    	send(ladro, "START", 5, 0);
    	do{	
    		recv(guardia, &pguardia, sizeof(pguardia), 0);  //ricevi la posizione della guardia
    		recv(ladro, &pladro, sizeof(pladro), 0);        //ricevi la posizione del ladro
    		send(guardia, &pladro, sizeof(pladro),0);	//invia alla guardia la posizione del ladro
    		send(ladro, &pguardia, sizeof(pguardia),0);	//invia al ladro la posizione della guardia
    	}while (collision(pguardia, pladro) != 0);		//controlla se coincidono
    	send(guardia, "Hai vinto\n", 10, 0);			//la guardia ha preso il ladro, comunica la vittoria
    	send(ladro, "Hai perso\n", 10, 0);			//comunica la sconfitta al ladro
    	close (guardia);
    	close(ladro);
    }
    
    int collision (struct pos a, struct pos b){			// verifica se le due posizioni coincidono
    	if((a.x == b.x) && (a.y == b.y)) 
    		return 1;
    	else 
    		return 0;
    }
    
    void prova (int guardia, int ladro){
    	struct pos position;
    	int i;
    	position.x=0;
    	position.y=100;
    	position.c='#';
    	send(guardia, "START", 5, 0);
    	send(ladro, "START", 5, 0);
    	for (i=0; i<10; i++){
    		send(guardia, &position, sizeof(position),0);
    		send(ladro, &position, sizeof(position),0);
    		position.x = position.x + i;
    		position.y = position.y - i;
    		printf("Inviato %c %d %d %d \n", position.c, position.x, position.y, i);
    	}
    	close (guardia);
    	close(ladro);
    }
    Client:
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <ctype.h>
    #include <sys/times.h>
    
    
    #define SERVER_PORT 1025
    #define MAX_CONN 10
    
    void startgame (int server);
    void prova (int server);
    
    
    struct pos {      	//rappresentazione delle coordinate del personaggio
    	char c;
    	int x;
    	int y;
    };
    
    int main () {
    	int sock, server_len;
    	struct sockaddr_in server;
    	char buf [31];
    	//creazione socket
    	if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    		perror("chiamata alla system call socket fallita");
    		exit(1);
    	}
    	server.sin_family = AF_INET;
    	server.sin_addr.s_addr = htonl(INADDR_ANY);
    	server.sin_port = htons(SERVER_PORT);
    	//connessione al server
    	server_len = sizeof(server);
    	if (connect(sock, (struct sockaddr *)&server, server_len) < 0) { 
    		perror("accepting connection");
    		exit(2);
    	}
    	do {
    		if (recv(sock, &buf, sizeof(buf), 0) < 0) {
    			perror("rcv error in main");
    			exit(3);	
    		}
    	}while(buf != "START");  // l'errore è in questo ciclo
    	//startgame(server);
    	prova (sock);
    }
    
    void prova (int server){
    	struct pos position;	
    	while (1){
    		printf("ciclo");
    		if (recv(server, &position, sizeof(position),0) < 0){
    			perror("rcv error in prova");
    			exit(4);		
    		}else{
    			printf("ricevuto %c %d %d \n", position.c, position.x, position.y);		
    		}
    	}
    }
    
    
    
    L'errore presumo sia nel do while, ma non riesco a capire perchè... Aggiungendo dei printf di prova (anche dopo la recv) il client continua a rimanere in ciclo infinito (quando in teoria dovrebbe comunque fermarsi ed attendere una send del server, o sbaglio?)
  • Re: Guardie e Ladri client/server

    Fai attenzione, non hai corretto tutti i punti:
    SERVER:
    
    max@studio:~> gcc server.c -Wall
    server.c: In function ‘main’:
    server.c:48:52: warning: pointer targets in passing argument 3 of ‘accept’ differ in signedness
    /usr/include/sys/socket.h:214:12: note: expected ‘socklen_t * __restrict__’ but argument is of type ‘int *’
    server.c:56:50: warning: pointer targets in passing argument 3 of ‘accept’ differ in signedness
    /usr/include/sys/socket.h:214:12: note: expected ‘socklen_t * __restrict__’ but argument is of type ‘int *’
    server.c: In function ‘startgame’:
    server.c:86:8: warning: implicit declaration of function ‘collision’
    max@studio:~>
    
  • Re: Guardie e Ladri client/server

    O ci allineiamo con le modifiche oppure non è pensabile ricorreggere gli errori!
  • Re: Guardie e Ladri client/server

    A me compilando non da quegli warning li... Probabilmente dipende dal compilatore che usiamo (io sto usando il comando gcc della shell di linux)
  • Re: Guardie e Ladri client/server

    Se non ti da quegli WARNING è perché compili senza l'opzione -Wall
    Nel caso specifico la accept non viene chiamata correttamente o meglio l'indirizzo e la grandezza della struct di ritorno non sono coerenti con la definizione del prototipo.
    Non mi sembra un'avvertenza trascurabile.
  • Re: Guardie e Ladri client/server

    Ho risolto il problema ma non capisco perchè il primo invio effettuato dal server non viene visualizzato correttamente dai client (visualizzano solo position.c invece che tutte le coordinate)
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <ctype.h>
    #include <sys/times.h>
    
    
    #define SERVER_PORT 1025
    #define MAX_CONN 10
    
    void startgame (int guardia, int ladro);
    void prova (int guardia, int ladro);
    
    
    struct pos {      	//rappresentazione delle coordinate del personaggio
    	char c;
    	int x;
    	int y;
    };
    
    int main () {
    	int sock, client_len, fdguardia, fdladro;
    	int waiting=0;
    	char prev='l';
    	struct sockaddr_in server, guardia, ladro;
    	if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    		perror("chiamata alla system call socket fallita");
    		exit(1);
    	}
    	server.sin_family = AF_INET;
    	server.sin_addr.s_addr = htonl(INADDR_ANY);
    	server.sin_port = htons(SERVER_PORT);
    	if (bind(sock, (struct sockaddr *)&server, sizeof server) == -1) {
    		perror("chiamata alla system call bind fallita");
    		exit(2);
    	}
    	listen(sock, MAX_CONN);
    	/* gestione delle connessioni dei clienti */
    	printf("Server avviato correttamente\n");
    	while (1) {
    		if (prev == 'l'){
    			client_len = sizeof (guardia);
    			if ((fdguardia = accept(sock, (struct sockaddr *)&guardia, &client_len)) < 0) { 
    				perror("accepting connection");
    				exit(3);
    			}
    			prev = 'g';
    		}
    		else{
    			client_len = sizeof (ladro);
    			if ((fdladro = accept(sock, (struct sockaddr *)&ladro, &client_len)) < 0) { 
    				perror("accepting connection");
    				exit(3);
    			}
    			prev = 'l';
    		}		
    		waiting++;
    		printf("ricevuta una connessione\n");
    		if (waiting >1){
    			waiting = waiting - 2;	
    			//startgame(fdguardia, fdladro);
    			prova (fdguardia, fdladro);
    	
    		} else 
    			send(fdguardia, "Ricerca giocatori in corso...\n", 31, 0);			
    	}
    	printf("Shutdown server\n");
    	close (sock);
    }
    
    
    void startgame (int guardia, int ladro){
    	struct pos pguardia, pladro;
    	send(guardia, "START", 5, 0);
    	send(ladro, "START", 5, 0);
    	send(guardia, "#",1,0); 
    	send(ladro, "$",1,0); 
    	do{	
    		recv(guardia, &pguardia, sizeof(pguardia), 0);  //ricevi la posizione della guardia
    		recv(ladro, &pladro, sizeof(pladro), 0);        //ricevi la posizione del ladro
    		send(guardia, &pladro, sizeof(pladro),0);	//invia alla guardia la posizione del ladro
    		send(ladro, &pguardia, sizeof(pguardia),0);	//invia al ladro la posizione della guardia
    	}while (collision(pguardia, pladro) != 0);		//controlla se coincidono
    	send(guardia, "Hai vinto\n", 10, 0);			//la guardia ha preso il ladro, comunica la vittoria
    	send(ladro, "Hai perso\n", 10, 0);			//comunica la sconfitta al ladro
    	close (guardia);
    	close(ladro);
    }
    
    int collision (struct pos a, struct pos b){			// verifica se le due posizioni coincidono
    	if((a.x == b.x) && (a.y == b.y)) 
    		return 1;
    	else 
    		return 0;
    }
    
    void prova (int guardia, int ladro){
    	struct pos position;
    	int i;
    	position.x=0;
    	position.y=100;
    	position.c='*';
    	send(guardia, "START\n", 6, 0);
    	send(ladro, "START\n", 6, 0);
    	for (i=0; i<10; i++){
    		printf("Sto inviando %c %d %d \n", position.c, position.x, position.y);
    		send(guardia, &position, sizeof(position),0);
    		send(ladro, &position, sizeof(position),0);
    		position.x = position.x + 1;
    		position.y = position.y - 1;
    		usleep(4000000);
    	}
    }
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <ctype.h>
    #include <sys/times.h>
    
    
    #define SERVER_PORT 1025
    #define MAX_CONN 10
    
    void startgame (int server);
    void prova (int server);
    
    
    struct pos {      	//rappresentazione delle coordinate del personaggio
    	char c;
    	int x;
    	int y;
    };
    
    int main () {
    	int sock, server_len;
    	struct sockaddr_in server;
    	char buf [31];
    	//creazione socket
    	if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    		perror("chiamata alla system call socket fallita");
    		exit(1);
    	}
    	server.sin_family = AF_INET;
    	server.sin_addr.s_addr = htonl(INADDR_ANY);
    	server.sin_port = htons(SERVER_PORT);
    	//connessione al server
    	server_len = sizeof(server);
    	if (connect(sock, (struct sockaddr *)&server, server_len) < 0) { 
    		perror("accepting connection");
    		exit(2);
    	}
    	do {
    		if (recv(sock, &buf, sizeof(buf), 0) < 0) {
    			perror("rcv error in main");
    			exit(3);	
    		} else printf("%s\n", buf);
    	}while(buf[0] != 'S');
    	//startgame(server);
    	prova (sock);
    }
    
    void prova (int server){
    	struct pos position;
    	while (1){
    		if (recv(server, &position, sizeof(position),0) < 0){
    			perror("rcv error in prova");
    			exit(4);		
    		}else{
    			printf("ricevuto %c %d %d \n", position.c, position.x, position.y);		
    		}
    	}
    }
    
    Se non ti da quegli WARNING è perché compili senza l'opzione -Wall
    Nel caso specifico la accept non viene chiamata correttamente o meglio l'indirizzo e la grandezza della struct di ritorno non sono coerenti con la definizione del prototipo.
    Non mi sembra un'avvertenza trascurabile.
    Adesso controllo allora
  • Re: Guardie e Ladri client/server

    Se non ti servono puoi passare 0 e 0

    edit:
    $ man 2 accept
    ...
    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    ...
    The argument addr is a pointer to a sockaddr structure. This structure is filled in with the address of the peer socket, as known to the communications layer. The exact format of the address returned addr is determined by the socket's address family (see socket(2) and the respective protocol man pages). When addr is NULL, nothing is filled in; in this case, addrlen is not used, and should also be NULL.
    ...
  • Re: Guardie e Ladri client/server

    C'è l'ho fatta... In sostanza gli invii si andavano a sovrapporre alle ricezioni, mettemdo una usleep tra un invio e l'altro funziona tutto.

    Finite le prove ho iniziato a scrivere il programma finale ha ho dei problemi con le fork (utilizzo nel server 3 processi, uno per creare le partite ogni due connessioni e due dentro la partita per comunicare con i client, e nei client un processo che "disegna" l'area di gioco e uno che comunica col server). Non riesco a capire per quale motivo il programma si blocca...

    server:
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <ctype.h>
    #include <sys/times.h>
    
    #define SERVER_PORT 1025
    #define MAX_CONN 10
    #define MAXX 80
    #define MAXY 24
    
    
    struct pos {      	//rappresentazione delle coordinate del personaggio
    	char c;
    	int x;
    	int y;
    };
    
    int collision (struct pos a, struct pos b){			// verifica se le due posizioni coincidono
    	if((a.x == b.x) && (a.y == b.y)) 
    		return 1;
    	else 
    		return 0;
    }
    
    
    void startgame (int guardia, int ladro){
    	struct pos pguardia, pladro;
    	int  pid_ladro, pid_guardia;
    	pguardia.x=0;
    	pguardia.y=0;
    	pguardia.c='#';
    	pladro.x=MAXX;
    	pladro.y=MAXY;
    	pladro.c='$';
    	send(guardia, "Sei la guardia\n", 15, 0);
    	send(ladro, "Sei il ladro\n", 13, 0);
    	usleep(100000);
    	send(guardia, "#",1,0); 
    	send(ladro, "$",1,0);
    	usleep(100000);
    	while ( collision (pguardia, pladro) == 0){
    		switch (pid_ladro = fork()){
    			case -1:
    				perror("Errore nell'esecuzione della fork (ladro)");
    				exit(4);
    			case 0:
    				recv(ladro, &pladro, sizeof(pladro),0);
    				send(guardia, &pladro, sizeof(pladro),0);
    			default:
    				switch (pid_guardia = fork()){
    					case -1:
    						perror("Errore nell'esecuzione della fork (guardia)");
    						exit(4);
    					case 0:
    						recv(guardia, &pguardia, sizeof(pguardia),0);
    						send(ladro, &pguardia, sizeof(pguardia),0);
    				}
    				
    		}
    		kill(pid_ladro, 1);
    		kill(pid_guardia,1);	
    	}
    	send(guardia, "Hai vinto!\n", 11, 0);
    	send(ladro, "Hai perso!\n", 11, 0);	
    }
    
    
    int main (int argc, char **argv) {
    	int sock, fdguardia, fdladro, pid_gioco;
    	int waiting=0;
    	char prev='l';
    	struct sockaddr_in server;
    	if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    		perror("chiamata alla system call socket fallita");
    		exit(1);
    	}
    	server.sin_family = AF_INET;
    	server.sin_addr.s_addr = htonl(INADDR_ANY);
    	server.sin_port = htons(SERVER_PORT);
    	if (bind(sock, (struct sockaddr *)&server, sizeof server) == -1) {
    		perror("chiamata alla system call bind fallita");
    		exit(2);
    	}
    	listen(sock, MAX_CONN);
    	/* gestione delle connessioni dei clienti */
    	printf("Server avviato correttamente\n");
    	while (1) {
    		if (prev == 'l'){
    			if ((fdguardia = accept(sock, NULL, 0)) < 0) { 
    				perror("accepting connection");
    				exit(3);
    			}
    			prev = 'g';
    		}
    		else{
    			if ((fdladro = accept(sock, NULL, 0)) < 0) { 
    				perror("accepting connection");
    				exit(3);
    			}
    			prev = 'l';
    		}		
    		waiting++;
    		printf("ricevuta una connessione\n");
    		if (waiting >1){
    			waiting = waiting - 2;
    			switch (pid_gioco = fork()){
    				case -1:
    					perror("Errore nell'esecuzione della fork (startgame)");
    					exit(4);
    				case 0:
    					printf("avvio startgame\n");
    					startgame(fdguardia, fdladro);			
    			}
    	
    		} else 
    			send(fdguardia, "Ricerca giocatori in corso...\n", 31, 0);			
    	}
    	printf("Shutdown server\n");
    	close (sock);
    }
    
    client:
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <ctype.h>
    #include <sys/times.h>
    #include <curses.h>
    
    
    #define SERVER_PORT 1025
    #define MAXX 80
    #define MAXY 24
    #define SU 65
    #define GIU 66
    #define SINISTRA 68
    #define DESTRA 67
    
    struct pos {      	//rappresentazione delle coordinate del personaggio
    	char c;
    	int x;
    	int y;
    };
    
    void aggiorna (struct pos* position, int server){
    	switch(getch()) {
    		case SU:
    			if(position->y>0)
    				position->y-=1;
    			break;
    		case GIU:
    			if(position->y<MAXY-1)
    				position->y+=1;	
    		break;
    		case SINISTRA:
    			if(position->x>0)
    				position->x-=1;
    			break;
    		case DESTRA:
    			if(position->x<MAXX-1)
    				position->x+=1;
    			break;
    		}
    	send(server, &position, sizeof(position), 0);
    }
    
    void visualizza (struct pos nuovo, struct pos* vecchio){
    	mvaddch(vecchio->y, vecchio->x, ' ');
    	mvaddch(nuovo.y, nuovo.x, nuovo.c);
    	curs_set(0);
    	refresh();
    	vecchio->x=nuovo.x;
    	vecchio->y=nuovo.y;
    }
    
    void startgame (int server){
    	struct pos miapos, suapos, supmia, supsua;
    	int pid_gioco, j;
    	char buf [11];
    	for (j=0; j<31; j++)
    		buf[j]='\0';
    	printf("attesa paramentri\n");
    	switch (recv(server, &buf, sizeof(buf), 0)){
    		case -1:
    			perror("errore di ricezione in startgame");
    			exit(4);
    		case '#':
    			miapos.x=0;
    			miapos.y=0;
    			miapos.c='#';
    			suapos.x=MAXX;
    			suapos.y=MAXY;
    			suapos.c='$';
    		default:
    			miapos.x=MAXX;
    			miapos.y=MAXY;
    			miapos.c='$';
    			suapos.x=0;
    			suapos.y=0;
    			suapos.c='#';	
    	} 
    	printf("ricevuti paramentri\n");
    	supmia=miapos;
    	supsua=suapos;
    	initscr();
    	noecho();
    	curs_set(0);
    	while(1){
    	switch (pid_gioco = fork()){
    		case -1:
    			perror("Errore nell'esecuzione della fork (gioco)");
    			exit(5);
    		case 0:
    			aggiorna(&miapos, server);
    			visualizza(miapos, &supmia);
    		default:
    			if(recv(server, &suapos, sizeof(suapos),0) < 0 ){
    				perror("Errore ricezione posizione avversario");
    				exit(4);
    			}else{
    				visualizza (suapos, &supsua);
    			}			
    	}
    	kill(pid_gioco,1);
    	}
    }
    
    
    int main () {
    	int sock, server_len, j;
    	struct sockaddr_in server;
    	char buf [31];
    	//creazione socket
    	if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    		perror("chiamata alla system call socket fallita");
    		exit(1);
    	}
    	server.sin_family = AF_INET;
    	server.sin_addr.s_addr = htonl(INADDR_ANY);
    	server.sin_port = htons(SERVER_PORT);
    	//connessione al server
    	server_len = sizeof(server);
    	if (connect(sock, (struct sockaddr *)&server, server_len) < 0) { 
    		perror("accepting connection");
    		exit(2);
    	}
    	do {
    		for (j=0; j<31; j++)
    			buf[j]='\0';
    		if (recv(sock, &buf, sizeof(buf), 0) < 0) {
    			perror("rcv error in main");
    			exit(3);	
    		} else printf("%s\n", buf);
    	}while(buf[0] != 'S');
    	printf("avvio startgame\n");
    	startgame(sock);
    }
    
    Ti ringrazio per l'aiuto che mi stai dando comunque!
Devi accedere o registrarti per scrivere nel forum
22 risposte