Ci sto provando ma non riesco a capire come scrivere il client ed il server... Io per ora sul server faccio 3 fork (una crea un processo che gestisce la comunicazione con la guarda, una comunica col ladro e la terza si occupa del timer), ed il padre esegue una wait() (quindi dovrebbe aspettare il termine di uno dei suoi figli) e dopodichè chiude le connessioni facendo close(guardia) e close(ladro). La partita però non termina allo scadere del timer ma solo quando la guarda "prende" il ladro. In più, il server non crea più nuove partite se arrivano altre connessioni (mentre nella versione senza timer lo faceva senza problemi).
Questi sono i codici della versione senza timer:
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 50
#define MAXY 18
#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;
};
struct pos miapos, suapos;
void visualizza (int pipein){ //aggiorna le posizioni a video
struct pos sup, miavec, suavec;
miavec=miapos;
suavec=suapos;
do {
read(pipein,&sup,sizeof(sup));
if(sup.c == miapos.c){
mvaddch(miavec.y,miavec.x,' ');
miavec=miapos;
miapos=sup;
}else{
mvaddch(suavec.y,suavec.x,' ');
suavec=suapos;
suapos=sup;
}
mvaddch(sup.y, sup.x, sup.c);
curs_set(0);
refresh();
} while (miapos.x != suapos.x || suapos.y != miapos.y);
}
void aggiorna (int server, int pipeout){
struct pos mia;
mia=miapos;
while(1){
char c;
switch(c = getch()) {
case SU:
if(mia.y>0)
mia.y-=1;
break;
case GIU:
if(mia.y<MAXY-1)
mia.y+=1;
break;
case SINISTRA:
if(mia.x>0)
mia.x-=1;
break;
case DESTRA:
if(mia.x<MAXX-1)
mia.x+=1;
break;
}
if(send(server, &mia, sizeof(mia), 0) > 0){
write(pipeout,&mia,sizeof(mia));
}else{
perror("errore di ricezione in aggiorna");
exit(5);
}
}
}
void ricevi (int server, int pipeout){
struct pos sua;
sua=suapos;
while(1){
if(recv(server, &sua, sizeof(sua), 0) > 0){
write(pipeout,&sua,sizeof(sua));
}else{
perror("errore di ricezione in ricevi");
exit(5);
}
}
}
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");
usleep(5000000);
//-------------------------------------------------------
int pid_gioco, pid_play;
char ruolo;
for (j=0; j<31; j++)
buf[j]='\0';
printf("attesa paramentri\n");
if(recv(sock, &buf, sizeof(buf), 0) < 0){
perror("errore di ricezione in startgame");
exit(4);
}
ruolo=buf[0];
printf("%s \n",buf);
switch (ruolo){
case '#':
miapos.x=0;
miapos.y=0;
miapos.c='#';
suapos.x=MAXX;
suapos.y=MAXY;
suapos.c='$';
break;
default :
miapos.x=MAXX;
miapos.y=MAXY;
miapos.c='$';
suapos.x=0;
suapos.y=0;
suapos.c='#';
break;
}
printf("ricevuti paramentri\n");
initscr(); /* inizializzazione dello schermo */
noecho(); /* i caratteri corrispondenti ai tasti premuti non saranno visualizzati sullo schermo del terminale */
mvaddch(miapos.y, miapos.x, miapos.c);
mvaddch(suapos.y, suapos.x, suapos.c);
curs_set(0);
refresh();
int filedes[2];
if(pipe(filedes)==-1) {
perror("Errore nella creazione della pipe.");
exit(6);
}
switch (pid_gioco = fork()){
case -1:
perror("Errore nell'esecuzione della fork (gioco)");
exit(5);
case 0: close(filedes[0]);
ricevi(sock, filedes[1]);
default:
switch (pid_play = fork()){
case -1:
perror("Errore nell'esecuzione della fork (gioco)");
exit(5);
case 0: close(filedes[0]);
aggiorna(sock, filedes[1]);
default: close(filedes[1]);
visualizza(filedes[0]);
}
}
kill(pid_gioco,1);
kill(pid_play,1);
endwin();
if(miapos.x==suapos.x && miapos.y==suapos.y && miapos.c=='#')
printf("\nCongratulazioni hai vinto\n\n");
else
printf("\nTi sei fatto prendere, hai perso\n\n");
//-------------------------------------------------------
}
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 50
#define MAXY 18
struct pos { //rappresentazione delle coordinate del personaggio
char c;
int x;
int y;
};
struct pos pguardia, pladro;
void cladro(int guardia, int ladro){//riceva da un clinet e invia dati all'altro
struct pos sup;
do{
if(pguardia.x!=pladro.x || pguardia.y!=pladro.y){
if(recv(ladro, &pladro, sizeof(pladro),0) > 0){
printf("ricevuto ladro\n");
printf("%c %d %d \n", pladro.c, pladro.x, pladro.y);
}
sup = pladro;
if(send(guardia, &sup, sizeof(sup),0) > 0){
printf("inviato guardia\n");
printf("%c %d %d \n\n", sup.c, sup.x, sup.y);
}
}
}while(pguardia.x!=pladro.x || pguardia.y!=pladro.y);
}
void cguardia(int guardia, int ladro){//riceva da un clinet e invia dati all'altro
struct pos sup;
do{
if(pguardia.x!=pladro.x || pguardia.y!=pladro.y){
if(recv(guardia, &pguardia, sizeof(pguardia),0) > 0){
printf("ricevuto guardia\n");
printf("%c %d %d \n", pguardia.c, pguardia.x, pguardia.y);
}
sup = pguardia;
if(send(ladro, &sup, sizeof(sup),0) > 0){
printf("inviato ladro\n");
printf("%c %d %d \n\n", sup.c, sup.x, sup.y);
}
}
}while(pguardia.x!=pladro.x || pguardia.y!=pladro.y);
}
void startgame (int pl1, int pl2){ //fa iniziare una partita
int pid_game, r, guardia, ladro;
pladro.x=MAXX;
pladro.y=MAXY;
pladro.c='$';
pguardia.x=0;
pguardia.y=0;
pguardia.c='#';
r=random();
if(r%2 == 0){
guardia=pl1;
ladro=pl2;
}else{
guardia=pl2;
ladro=pl1;
}
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);
switch (pid_game = fork()){
case -1:
perror("Errore nell'esecuzione della fork (ladro)");
exit(4);
case 0: cladro(guardia, ladro);
default: cguardia(guardia, ladro);
}
kill(pid_game, 1);
}
int main (int argc, char **argv) {
int sock, fdpl1, fdpl2, 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 ((fdpl1 = accept(sock, NULL, 0)) < 0) {
perror("accepting connection");
exit(3);
}
prev = 'g';
}
else{
if ((fdpl2 = 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(fdpl1, fdpl2);
}
} else
send(fdpl1, "Ricerca giocatori in corso...\n", 31, 0);
}
printf("Shutdown server\n");
close (sock);
}
Mentre questo è il server con il timer:
#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 <sys/wait.h>
#define SERVER_PORT 1025
#define MAX_CONN 10
#define MAXX 50
#define MAXY 18
struct pos { //rappresentazione delle coordinate del personaggio
char c;
int x;
int y;
};
struct pos pguardia, pladro;
void cladro(int guardia, int ladro){//riceva da un clinet e invia dati all'altro
struct pos sup;
do{
if(pguardia.x!=pladro.x || pguardia.y!=pladro.y){
if(recv(ladro, &pladro, sizeof(pladro),0) > 0){
printf("ricevuto ladro\n");
printf("%c %d %d \n", pladro.c, pladro.x, pladro.y);
}
sup = pladro;
if(send(guardia, &sup, sizeof(sup),0) > 0){
printf("inviato guardia\n");
printf("%c %d %d \n\n", sup.c, sup.x, sup.y);
}
}
}while(pguardia.x!=pladro.x || pguardia.y!=pladro.y);
}
void cguardia(int guardia, int ladro){//riceva da un clinet e invia dati all'altro
struct pos sup;
do{
if(pguardia.x!=pladro.x || pguardia.y!=pladro.y){
if(recv(guardia, &pguardia, sizeof(pguardia),0) > 0){
printf("ricevuto guardia\n");
printf("%c %d %d \n", pguardia.c, pguardia.x, pguardia.y);
}
sup = pguardia;
if(send(ladro, &sup, sizeof(sup),0) > 0){
printf("inviato ladro\n");
printf("%c %d %d \n\n", sup.c, sup.x, sup.y);
}
}
}while(pguardia.x!=pladro.x || pguardia.y!=pladro.y);
}
void startgame (int pl1, int pl2, int timer){ //fa iniziare una partita
int pid_ladro, pid_guardia, pid_timer, status;
int r, guardia, ladro;
pladro.x=MAXX;
pladro.y=MAXY;
pladro.c='$';
pguardia.x=0;
pguardia.y=0;
pguardia.c='#';
r=random();
if(r%2 == 0){
guardia=pl1;
ladro=pl2;
}else{
guardia=pl2;
ladro=pl1;
}
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);
switch (pid_ladro = fork()){
case -1:
perror("Errore nell'esecuzione della fork (ladro)");
exit(4);
case 0: cladro(guardia, ladro);
default:
switch (pid_guardia = fork()){
case -1:
perror("Errore nell'esecuzione della fork (guardia)");
exit(4);
case 0:
cguardia(guardia, ladro);
default:
switch(pid_timer = fork()){
case -1:
perror("Errore nell'esecuzione della fork (timer)");
exit(4);
case 0:
sleep(timer);
default:
wait(&status);
close(guardia);
close(ladro);
}
}
}
}
int main (int argc, char **argv) {
int sock, fdpl1, fdpl2, pid_gioco;
int waiting=0, timer;
char prev='l';
struct sockaddr_in server;
if (argc > 1)
timer = atoi(argv[1]);
else {
printf("Non hai inserito la durata massima della partita!\n");
return 0;
}
if (timer < 1){
printf("La durata massima della partita inserita non è valida!\n");
return 0;
}
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 ((fdpl1 = accept(sock, NULL, 0)) < 0) {
perror("accepting connection");
exit(3);
}
prev = 'g';
}
else{
if ((fdpl2 = 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(fdpl1, fdpl2, timer);
}
} else
send(fdpl1, "Ricerca giocatori in corso...\n", 31, 0);
}
printf("Shutdown server\n");
close (sock);
}