Systemy Rozproszone Zad 1

Takie zadanie dostaliśmy na laboratorium systemów rozproszonych:

Napisać serwer obsługujący grę w kółko i krzyżyk. Użytkownik jako programu klienta używa programu telnet.
Komunikacja między klientem a serwerem odbywa się za pomocą protokołu TCP przez wymianę tekstów.
Serwer wysyła do klienta w trybie tekstowym aktualną sytuację na planszy. Klient wysyła swoje ruchy też w postaci tekstowej.

Serwer po odebraniu połączenia od klienta oczekuje pewien ustalony czas i jeśli w tym czasie zgłosi się drugi klient, to serwer łączy tych klientów w parę, rozgrywającą partię między sobą.
Serwer jest wtedy pośrednikiem w tej grze. Jeśli w zadanym czasie nie zgłosi się drugi klient, to serwer przejmuje jego rolę i staje się partnerem w grze. Jeśli w czasie gry któryś z pary graczy rozłączy się, to serwer i w tym przypadku przejmuje jego rolę i kontynuuje grę za niego. Komunikacja między klientem a serwerem powinna być identyczna niezależnie od tego, czy klient gra z serwerem, czy z innym klientem.

Serwer musi móc równocześnie obsługiwać wielu pojedynczych klientów i wiele par klientów. Serwer powinien być odporny na różne złośliwe zachowania klienta: dane niezgodne z oczekiwanymi, nagłe zerwanie połączenia itp. Serwer utrzymuje wszystkie niezbędne informacje o wszystkich rozgrywanych w danym momencie grach. Serwer musi dbać o zwalnianie zasobów po odłączeniu się klienta. Program powinien być napisany w C lub C++ z użyciem interfejsu gniazd.

Gra jest tylko pretekstem dla implementacji komunikacji sieciowej i serwer nie musi implementować żadnej rozsądnej strategii. Serwer może grać w sposób zupełnie przypadkowy, byle zgodnie z zasadami gry. Serwer powinien jakoś reagować na niepoprawne zagrania klienta.

A oto rozwiązanie:

#include 
#include  
#include 
#include 
#include 
#include 


int plansza[3][3];	//Dla planszy
int polaczony;		//Czy klient 2 jest podlaczony
int newsockfd2;		//Socket klienta 2

void gra(int,int);

void error(char *msg)
{
    perror(msg);
    exit(1);
}


void* thr(void *sockfd)
{
	//Tworzy watek podlaczajacy klienta.
	int *sock;
	int clilen2,sock2;
	struct sockaddr_in cli2_addr;
	printf("Startuje watekn");
	sock=(int *)sockfd;
	sock2=*sock;
    newsockfd2 = accept(sock2, 
        (struct sockaddr *) &cli2_addr, &clilen2);
    if (newsockfd2 < 0) 
        error("BLAD podczas accept klienta 2 n");
	printf("Klient podlaczonyn");
	polaczony=1;
}

int main(int argc, char *argv[])
{
     int sockfd,sockfd2, newsockfd, portno, clilen, pid,watek,i;
     struct sockaddr_in serv_addr, cli_addr, cli2_addr;
	 pthread_t tr;

	printf("Startujemy serwer n");
	 polaczony=0;
	 //Budujemy serwer:
     if (argc < 2) {
         fprintf(stderr,"BLAD, brak portu.n");
         exit(1);
     }
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0) 
        error("BLAD otwierajac socket n");
     bzero((char *) &serv_addr, sizeof(serv_addr));
     portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
	 //Bind i sluchamy:
     if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0) 
              error("ERROR on binding");
     listen(sockfd,5);
     clilen = sizeof(cli_addr);
	 
	 //Petla.  Czekamy na przychodzace polozenia.
     while (1) {
		//Podlaczenie klienta 1.
		
		if(polaczony==0)
		{
			watek = pthread_create( &tr, NULL,thr, (void*) &sockfd);
			while(polaczony==0)
			{
				sleep(1);
			}
		}
		newsockfd=newsockfd2;
		polaczony=0;
		
		//Podlaczenie klienta 2.
		watek = pthread_create( &tr, NULL,thr, (void*) &sockfd);
		/////////////////////
		
		for (i=0;i<10;i++)
		{
			if(polaczony==0)
			{
				sleep(1);
			}
			else
			{
				break;
			}
		}
		

		//No i oddzielamy od glownego procesu.
         pid = fork();
         if (pid < 0)
             error("BLAD podczas fork. n");
         if (pid == 0)  {
			//Stary proces.
			//Zamykamy niepotrzebne gniazdo.
             close(sockfd);
			//Zaczynamy gre,
             gra(newsockfd,newsockfd2);
             exit(0);
         }
         else close(newsockfd);
     }
     return 0;
}

/*****************GRA*********************
Tu sie zaczyna sama gra,
 *****************************************/
 
int wypisz(char wynik[15])
{
	//Funkcja sprawdza wynik, wypisuje co trzeba.
	int i,j,zwr,wolnych;
	zwr=0;
	wolnych=0;
	
	
	//sprawdczamy czy sa wolne miejsca na planszy
	for(i=0;i<3;i++)
	{
		for(j=0;j<3;j++)
		{
			if(plansza[i][j]==0)
			{
				wolnych++;
			}
		}
	}
	
	if(wolnych==0)
	{
		zwr=-1;
	}
	
	//sprawdzamy w wierszach
	for(i=0;i0))
			zwr=plansza[i][2];
			
	}
	
	//W kolumnach
	for(i=0;i0))
			zwr=plansza[2][i];
	}
	
	//W skosach
	if((plansza[0][0]==plansza[1][1])&&(plansza[1][1]==plansza[2][2])&&(plansza[2][2]>0))
		zwr=plansza[2][2];
		
	if((plansza[0][2]==plansza[1][1])&&(plansza[1][1]==plansza[2][0])&&(plansza[2][0]>0))
		zwr=plansza[2][0];

		
	//Koniec sprawdzania wyniku.
	
	/*if(zwr==-1)
	{
		wynik=" NIEROZEGRANErn";
	}
	else if(zwr==1)
	{
		wynik="Gre wygral Xrn";
	}
	else if(zwr==2)
	{
		wynik="Gre wygral Orn";
	}
	else
	{*/
	
		//Wypisujemy wynik
		for(i=0;i<3;i++)
		{
			for(j=0;j<3;j++)
			{
				if(plansza[i][j]==0)
				{
					wynik[(i)*5+j]=' ';
				}
				else if(plansza[i][j]==1)
				{
					wynik[(i)*5+j]='X';
				}
				else if(plansza[i][j]==2)
				{
					wynik[(i)*5+j]='O';
				}
			}
			wynik[(i)*5+3]='r';
			wynik[(i)*5+4]='n';		
		}
	//}
	return zwr;
}


// 'Sztuczna inteligencja' na poziomie wspolczesnego gimnazjalisty. Wstawia w pierwsze wolne miejsce.
int AIruch(int gracz)
{
	int i,j;
	i=0;
	j=0;
	
	while((plansza[i][j]!=0)&&(i2)
		{
			j=0;
			i++;
		}
	}
	
	if(i<3)
	{
		plansza[i][j]=gracz;
	}
	
	return 0;
}


 
void gra (int sock,int sock2)
{
	//Sama gra.
   int i,j,n;
   char buffer[256];
   char wynik[15];
	int ruch;
	int rozgrywka;
	int dwoch;
	
	//Init
   	for(i=0;i<3;i++)
	{
		for(j=0;j<3;j++)
		{
			plansza[i][j]=0;
		}
	}
	
	rozgrywka=0;
	dwoch=1;
	
   
   //Dopoki gra sie nie skonczyla
	while(rozgrywka==0)
	{
	// Kolejne ruchy.
		write(sock,"Nowa tura graczu X rn",21);
		write(sock2,"Nowa tura graczu O rn",21);
		
		//Dopoki nie wykonany prawidlowefggo ruchu
		ruch=0;
		while(ruch==0)
		{

			j=5;
			i=5;
			
			//Dopoki nie wpisano prawidlowego znaku
			while((i2))
			{
				bzero(buffer,256);
				write(sock,"Wpisz wiersz graczu X rn",24);
				read(sock,buffer,256);
				i=0;
				while((i<256)&&((buffer[i]'3')))
				{
						i++;
				}
				
				i=buffer[i]-49;
			}
			
			//Wopoki nie dobry znak
			while((j2))
			{
				bzero(buffer,256);
				write(sock,"Wpisz kolumne graczu X rn",25);
				read(sock,buffer,256);
				j=0;
				while((j<256)&&((buffer[j]'3')))
				{
						j++;
				}
				j=buffer[j]-49;
			}
		
			//Wykonujemy ruch.
			if(plansza[i][j]==0)
			{
				plansza[i][j]=1;
				ruch=1;
			}
		}
		
		rozgrywka=wypisz(wynik);
		ruch=0;
		
		//Jesli klient 2 jest podlaczony
		if(polaczony==1)
		{
			
			//I tak samo.
			while((ruch==0)&&(rozgrywka==0))
			{
				write(sock2,wynik,15);
				i=5;
				while((i2))
				{
					bzero(buffer,256);
					write(sock2,"Wpisz wiersz graczu O rn",24);
					read(sock2,buffer,256);
					i=0;
					while((i<256)&&((buffer[i]'3')))
					{
							i++;
					}
					
					i=buffer[i]-49;
				}
				


				j=5;
				while((j2))
				{
					bzero(buffer,256);
					write(sock2,"Wpisz kolumne graczu O rn",25);
					read(sock2,buffer,256);
					j=0;
					while((j<256)&&((buffer[j]'3')))
					{
							j++;
					}
					j=buffer[j]-49;
				}
			
				//Wykonujemy ruch.
				if(plansza[i][j]==0)
				{
					plansza[i][j]=2;
					ruch=1;
				}
				
				
			}//Ruchy wykonane.
		}
		else
		{
		//Jesli klient 2 nie podlaczony - intelygencyja
			AIruch(2);
		}
		
		rozgrywka=wypisz(wynik);
		write(sock,wynik,15);
	}
	
	write(sock,wynik,15);
	if(polaczony==1)
	{
	write(sock,wynik,15);
	}
	printf("Gra skonczona - wynik: [%i]n%sn",rozgrywka,wynik);
}





Leave a Reply