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

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);
}






Follow the thread

Start here

Eight essays connecting disciplines, useful progress, and deliberate choices.

Writing archive

Browse the complete archive, including technical, personal, travel, and book writing.

Projects

Tools and experiments where the ideas meet practical work.

Leave a Reply

Discover more from Artur Piszek

Subscribe now to keep reading and get access to the full archive.

Continue reading