/* ____________________________________________________________________________ Dots - server Jedna se o program, ktery slouzi jako server pro hru Dots. Program je napsan v programovacim jazyce C. Autor: Jan Novak A11B0442P ____________________________________________________________________________ */ #include #include #include #include #include #include #include #include #include #include "cara.h" #include "ctverec.h" #include #include /* ____________________________________________________________________________ Struktura hry Deklarace struktury pro jednotlive hry, dochazi k uchovani klientskych socketu pro jednu hru. ____________________________________________________________________________ */ typedef struct hra_s { int client_socket1; int client_socket2; }HRA_S; /* ____________________________________________________________________________ Globální promněnný ____________________________________________________________________________ */ int server_socket = 0; /* Deklarace server socketu */ int pocetHracu = 0; /* Deklarace poctu hracu */ FILE *f; /* Deklarace souboru */ time_t cas,casGlob; /* Deklarace casu */ //int wind = 0; /* Deklarace ukonceni klientu*/ int sumPr, sumPrP, sumOd, sumOdP; /* Deklarace pro soucet prenesenych dat*/ /*____________________________________________________________________________ void vypisSoubor(int socket, int velikost, int typ) Funkce zapisujici ulozeni data do souboru. Parametry jsou klientsky socket, pocet bytu a cislo, co znaci, co se bude zapisovat. Kdyz je typ 0 - server prijal, 1 - server odeslal, 3 - klient se odpojil. ____________________________________________________________________________ */ void vypisSoubor(int socket, int velikost, int typ){ cas = time(NULL); struct tm *localCas; localCas = localtime(&cas); int paket = 0; if(typ == 0){ if(velikost < 1500){ fprintf(f, "%02i:%02i:%02i - Client_socker: %d prijal %d bytu = 1 packet. \n", localCas->tm_hour, localCas->tm_min, localCas->tm_sec, socket, velikost); sumPr = sumPr + velikost; sumPrP++; } else if (velikost > 1500){ fprintf(f, "%02i:%02i:%02i - Client_socker: %d prijal %d bytu = 2 packet. \n", localCas->tm_hour, localCas->tm_min, localCas->tm_sec, socket, velikost); sumPr = sumPr + velikost; sumPrP=sumPrP+2; } } else if(typ == 1){ if(velikost < 1500){ fprintf(f, "%02i:%02i:%02i - Client_socker: %d odeslal %d bytu = 1 packet. \n", localCas->tm_hour, localCas->tm_min, localCas->tm_sec, socket, velikost); sumOd = sumOd + velikost; sumOdP++; } else if (velikost > 1500){ fprintf(f, "%02i:%02i:%02i - Client_socker: %d odeslal %d bytu = 2 packet. \n", localCas->tm_hour, localCas->tm_min, localCas->tm_sec, socket, velikost); sumOd = sumOd + velikost; sumOdP=sumOdP+2; } } else if(typ == 3){ fprintf(f, "%02i:%02i:%02i - Client_socker: %d se odpojil a bylo odeslano %d bytu = 1 packet. \n", localCas->tm_hour, localCas->tm_min, localCas->tm_sec, socket, velikost); sumOd = sumOd + velikost; sumOdP++; } //free(localCas); //localCas = NULL; } /* ____________________________________________________________________________ void overCtverec(Cara *p_cara, Ctverec *p_ctverec, HRA_S *hra_pom, int barva) Funkce zajistuje overeni, zda po pridani cary, byl vytvoren ctverec. Nasledne vyhodnocena informace je poslana klientum. Prvni parametr je ukazatel na pole, ve kterem se uchovavaji vytvorene cary, druhy parametr je ukazatel na pole vsech moznych kombinaci ctvercu, treti paramet je ukazatel na strukturu hry, ve kterem jsou uchovany klientske sockety, ctvrty parametr slouzi pro prirazeni barvy ctverce. ____________________________________________________________________________ */ void overCtverec(Cara *p_cara, Ctverec *p_ctverec, HRA_S *hra_pom, int barva){ int v1=0; int v2=0; int s1=0; int s2=0; int i=0; int j=0; int pocetBajtu; int naselSe = 0; char cbufOut1[256]; char cbufOut2[256]; printf("\nOveruju ctverec.\n"); while(1){ for(i=1; i<36; i++){ Ctverec pomCt = p_ctverec[i]; if(pomCt.existuje == 1){ continue; } v1=0; v2=0; s1=0; s2=0; for(j=0; j<90; j++){ Cara pomCara = p_cara[j]; if( ((pomCt.v1.od_x == pomCara.od_x) && (pomCt.v1.od_y == pomCara.od_y) && (pomCt.v1.kam_x == pomCara.kam_x) && (pomCt.v1.kam_y == pomCara.kam_y)) || ((pomCt.v1.od_x == pomCara.kam_x) && (pomCt.v1.od_y == pomCara.kam_y) && (pomCt.v1.kam_x == pomCara.od_x) && (pomCt.v1.kam_y == pomCara.od_y)) ){ v1 = 1; } if( ((pomCt.v2.od_x == pomCara.od_x) && (pomCt.v2.od_y == pomCara.od_y) && (pomCt.v2.kam_x == pomCara.kam_x) && (pomCt.v2.kam_y == pomCara.kam_y)) || ((pomCt.v2.od_x == pomCara.kam_x) && (pomCt.v2.od_y == pomCara.kam_y) && (pomCt.v2.kam_x == pomCara.od_x) && (pomCt.v2.kam_y == pomCara.od_y)) ){ v2 = 1; } if( ((pomCt.s1.od_x == pomCara.od_x) && (pomCt.s1.od_y == pomCara.od_y) && (pomCt.s1.kam_x == pomCara.kam_x) && (pomCt.s1.kam_y == pomCara.kam_y)) || ((pomCt.s1.od_x == pomCara.kam_x) && (pomCt.s1.od_y == pomCara.kam_y) && (pomCt.s1.kam_x == pomCara.od_x) && (pomCt.s1.kam_y == pomCara.od_y)) ){ s1 = 1; } if( ((pomCt.s2.od_x == pomCara.od_x) && (pomCt.s2.od_y == pomCara.od_y) && (pomCt.s2.kam_x == pomCara.kam_x) && (pomCt.s2.kam_y == pomCara.kam_y)) || ((pomCt.s2.od_x == pomCara.kam_x) && (pomCt.s2.od_y == pomCara.kam_y) && (pomCt.s2.kam_x == pomCara.od_x) && (pomCt.s2.kam_y == pomCara.od_y)) ){ s2 = 1; } if(v1 == 1 && v2 == 1 && s1 == 1 && s2 == 1){ p_ctverec[i].existuje = 1; //nastaveni pro preskakovani dalsich kontrol naselSe++; if(naselSe == 1){ sprintf(cbufOut1, "s;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;", pomCt.v1.od_x, pomCt.v1.od_y, pomCt.v1.kam_x, pomCt.v1.kam_y, pomCt.v2.od_x, pomCt.v2.od_y, pomCt.v2.kam_x, pomCt.v2.kam_y, pomCt.s1.od_x, pomCt.s1.od_y, pomCt.s1.kam_x, pomCt.s1.kam_y, pomCt.s2.od_x, pomCt.s2.od_y, pomCt.s2.kam_x, pomCt.s2.kam_y, barva); } if(naselSe == 2){ sprintf(cbufOut2, "%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;", pomCt.v1.od_x, pomCt.v1.od_y, pomCt.v1.kam_x, pomCt.v1.kam_y, pomCt.v2.od_x, pomCt.v2.od_y, pomCt.v2.kam_x, pomCt.v2.kam_y, pomCt.s1.od_x, pomCt.s1.od_y, pomCt.s1.kam_x, pomCt.s1.kam_y, pomCt.s2.od_x, pomCt.s2.od_y, pomCt.s2.kam_x, pomCt.s2.kam_y ); } //printf("odesli klientum existujici ctverec"); v1=0; v2=0; s1=0; s2=0; } } } break; } if(naselSe == 1){ usleep(50000); pocetBajtu = send(hra_pom->client_socket1, cbufOut1, strlen(cbufOut1)*sizeof(char), 0); vypisSoubor(hra_pom->client_socket1,pocetBajtu, 1); pocetBajtu = send(hra_pom->client_socket2, cbufOut1, strlen(cbufOut1)*sizeof(char), 0); vypisSoubor(hra_pom->client_socket2,pocetBajtu, 1); bzero(cbufOut1, 256); } if(naselSe == 2){ //podminka ze kdyz uz se nejakej ctverec nasel tak aby se do sendu neulozilo Z int a = 0; int b = 0; cbufOut1[0]='h'; for(a=strlen(cbufOut1); a<256;a++){ cbufOut1[a] = cbufOut2[b]; b++; } usleep(50000); pocetBajtu = send(hra_pom->client_socket1, cbufOut1, strlen(cbufOut1)*sizeof(char), 0); vypisSoubor(hra_pom->client_socket1,pocetBajtu, 1); pocetBajtu = send(hra_pom->client_socket2, cbufOut1, strlen(cbufOut1)*sizeof(char), 0); vypisSoubor(hra_pom->client_socket2,pocetBajtu, 1); /* for(a=0; aclient_socket1, cbufOut, strlen(cbufOut)*sizeof(char),0); vypisSoubor(hra_pom->client_socket1,pocetBajtu, 1); pocetBajtu = send(hra_pom->client_socket2, cbufOut, strlen(cbufOut)*sizeof(char),0); vypisSoubor(hra_pom->client_socket2,pocetBajtu, 1); bzero(cbufOut, 256); *barva = (*barva + 1); *indexCara = (*indexCara + 1); printf("\nCara je pridana."); return 1; } if(test == 0){ cbufOut[0]= 'd'; cbufOut[1]= ';'; usleep(50000); if((*barva%2)==1){ pocetBajtu = send(hra_pom->client_socket1, cbufOut, 2*sizeof(char), 0); vypisSoubor(hra_pom->client_socket1,pocetBajtu, 1); } if((*barva%2)==0){ pocetBajtu = send(hra_pom->client_socket2, cbufOut, 2*sizeof(char), 0); vypisSoubor(hra_pom->client_socket2,pocetBajtu, 1); } bzero(cbufOut, 256); printf("\nCara jiz existuje.\n"); return 0; } } else{ cbufOut[0]= 'f'; cbufOut[1]= ';'; usleep(50000); if((*barva%2)==1){ pocetBajtu = send(hra_pom->client_socket1, cbufOut, 2*sizeof(char), 0); vypisSoubor(hra_pom->client_socket1,pocetBajtu, 1); } if((*barva%2)==0){ pocetBajtu = send(hra_pom->client_socket2, cbufOut, 2*sizeof(char), 0); vypisSoubor(hra_pom->client_socket2,pocetBajtu, 1); } bzero(cbufOut, 256); printf("\nCaru nelze vytvorit."); return 0; } } /* ____________________________________________________________________________ void *naslouchej(void *arg){ Funkce slouzi pro detekci klienta, zda se neodpojil, kdyz neni na tahu. Parametr je klientsky socket. ____________________________________________________________________________ */ void *naslouchej(void *arg){ HRA_S *hra_pom; hra_pom = (HRA_S *)arg; int pocetBajtu = 0; printf("Hrac_naslouzej: %d\n", hra_pom->client_socket2); char cbufIn[256]; pocetBajtu = recv(hra_pom->client_socket2, cbufIn, 256*sizeof(char), 0); vypisSoubor(hra_pom->client_socket2,pocetBajtu, 0); if(cbufIn[0] == 'k'){ //printf("Padl klient se socketem %d\n",hra_pom->client_socket2); bzero(cbufIn, 256); cbufIn[0] = 'v'; cbufIn[1] = ';'; pocetBajtu = send(hra_pom->client_socket1, cbufIn , 2*sizeof(char), 0); //wind = 1; //vypisSoubor(hra_pom->client_socket1,pocetBajtu, 3); } //free(hra_pom); } /* ____________________________________________________________________________ void *aplikace(void *pom) Funkce vlakna hry, do ktere skoci hra po spravnem pripojeni klientu k serveru. Zde probiha prijem hodnot zadanych od klienta, ktere jsou bud v poradku a nasledne dochazi k volanim funkci, nebo k cekani na dalsi hodnoty od klienta. Paramet je ukazatel na strukturu hry, ve kterem jsou uchovany klientske sockety. ____________________________________________________________________________ */ void *aplikace(void *pom){ struct hra_s *hra_pom; hra_pom = (HRA_S *)pom; printf("Hrac 1: %d\n", hra_pom->client_socket1); printf("Hrac 2: %d\n", hra_pom->client_socket2); Ctverec *poleCtverec = vrat_ctverce(); ; Cara *poleCara = initCara(); //vypis_ctverec(poleCtverec); pthread_t klient1; pthread_t klient2; char cbufIn[256]; //null char *parsovani = (char*)malloc(256*sizeof(char)); int *poleCaraOver = (int*)malloc(4*sizeof(int)); int i = 0; int j = 0; int k,l,ok; int pocetBajtu = 0; int barva = 1; int indexCara = 0; int pocitadloHrac = 0; int over = 0; while(1){ int pocetChyb = 0; if((pocitadloHrac % 2) == 0){ HracJedna: usleep(1000000); cbufIn[0] = 'a'; cbufIn[1] = ';'; pocetBajtu = send(hra_pom->client_socket1, cbufIn , 2*sizeof(char), 0); vypisSoubor(hra_pom->client_socket1,pocetBajtu, 1); printf("\nOdeslano: %d %s\n", hra_pom->client_socket1, cbufIn); bzero(cbufIn, 256); HRA_S hra_over; hra_over.client_socket1 = hra_pom->client_socket1; hra_over.client_socket2 = hra_pom->client_socket2; pthread_create(&klient1, NULL, (void *)&naslouchej, &hra_over); pocetBajtu = recv(hra_pom->client_socket1, cbufIn, 256*sizeof(char), 0); if(pocetBajtu != 0 && pocetBajtu== -1){ vypisSoubor(hra_pom->client_socket1,pocetBajtu, 0); } if( pocetBajtu == 0){ //printf("Ztrata spojeni.\n"); cbufIn[0] = 'v'; cbufIn[1] = ';'; pocetBajtu = send(hra_pom->client_socket2, cbufIn , 2*sizeof(char), 0); vypisSoubor(hra_pom->client_socket1,pocetBajtu, 3); vypisSoubor(hra_pom->client_socket2,pocetBajtu, 3); bzero(cbufIn, 256); pthread_cancel(klient1); //printf("odeslal jsem a ukoncuju\n"); break; } else{ /* if(wind == 1){ break; }*/ if(pocetChyb == 4){ bzero(cbufIn, 256); cbufIn[0] = 'x'; cbufIn[1] = ';'; //send(hra_pom->client_socket1, cbufIn , 2*sizeof(char), 0); send(hra_pom->client_socket2, cbufIn , 2*sizeof(char), 0); break; } ok = 0; for(k=0; k<7; k=k+2){ for(l=49; l<57; l++){ if(cbufIn[k] == l){ ok++; } } } if(ok < 4){ printf("Ty ulicniku :-D\n"); pocetChyb++; //ok = 0; pthread_cancel(klient1); goto HracJedna; } } printf("Prijato od: %d - ", hra_pom->client_socket1); pthread_cancel(klient1); } else{ HracDva: usleep(1000000); cbufIn[0] = 'a'; cbufIn[1] = ';'; pocetBajtu = send(hra_pom->client_socket2, cbufIn , 2*sizeof(char), 0); vypisSoubor(hra_pom->client_socket2,pocetBajtu, 1); printf("\nOdeslano: %d %s\n", hra_pom->client_socket2, cbufIn); bzero(cbufIn, 256); HRA_S hra_over; hra_over.client_socket1 = hra_pom->client_socket2; hra_over.client_socket2 = hra_pom->client_socket1; pthread_create(&klient2, NULL, (void *)&naslouchej, &hra_over); pocetBajtu = recv(hra_pom->client_socket2, cbufIn, 256*sizeof(char), 0); if(pocetBajtu != 0 && pocetBajtu== -1){ vypisSoubor(hra_pom->client_socket2,pocetBajtu, 0); } if( pocetBajtu == 0){ //printf("Ztrata spojeni.\n"); cbufIn[0] = 'v'; cbufIn[1] = ';'; pocetBajtu = send(hra_pom->client_socket1, cbufIn , 2*sizeof(char), 0); vypisSoubor(hra_pom->client_socket2,pocetBajtu, 3); vypisSoubor(hra_pom->client_socket1,pocetBajtu, 3); bzero(cbufIn, 256); pthread_cancel(klient2); //printf("Odeslal jsem a ukoncuju.\n"); break; } else{ /* if(wind == 1){ break; }*/ if(pocetChyb == 4){ bzero(cbufIn, 256); cbufIn[0] = 'x'; cbufIn[1] = ';'; send(hra_pom->client_socket1, cbufIn , 2*sizeof(char), 0); //send(hra_pom->client_socket2, cbufIn , 2*sizeof(char), 0); break; } ok = 0; for(k=0; k<7; k=k+2){ for(l=49; l<57; l++){ if(cbufIn[k] == l){ ok++; } } } if(ok < 4){ printf("Ty ulicniku :-D\n"); pocetChyb++; //ok = 0; pthread_cancel(klient2); goto HracDva; } } printf("Prijato od: %d - ", hra_pom->client_socket2); pthread_cancel(klient2); } parsovani = strtok (cbufIn,";"); while (parsovani != NULL) { poleCaraOver[i] = atoi(parsovani); printf ("%d", poleCaraOver[i]); parsovani = strtok (NULL, " ;"); i++; } bzero(cbufIn, 256); i = 0; //nulovani pro parsovani over = overCaru(poleCaraOver, hra_pom, poleCara, &barva, &indexCara); //printf("\nCara overena.\n"); if(over == 1) { overCtverec(poleCara, poleCtverec, hra_pom, barva); pocitadloHrac++; over = 0; usleep(100000); } } printf("Uvolnuju hru.\n"); free(poleCtverec); free(poleCara); free(poleCaraOver); free(parsovani); free(hra_pom); poleCtverec = NULL; poleCara = NULL; poleCaraOver = NULL; parsovani = NULL; hra_pom = NULL; } /* ____________________________________________________________________________ void *server() Funkce vlakna pro naslouchani na serveru. Dochazi k otevreni a zavreni souboru, do ktereho se ukladaji informace o serveru. Prikaz q ukonci server. ____________________________________________________________________________ */ void *server(){ printf("Vlakno pro komunikaci se servrem bezi.\n"); f = fopen("text.txt", "w"); fclose(f); f = fopen("text.txt", "a"); fprintf(f,"--------------------------------------------------\n"); fprintf(f,"Server byl spusten.\n"); fprintf(f,"--------------------------------------------------\n"); char operace; while(1){ scanf("%c", &operace); if(operace == 'q'){ fprintf(f,"--------------------------------------------------\n"); fprintf(f,"Celkem bylo odeslano %02d bytu a %02d packetu.\n", sumOd, sumOdP); fprintf(f,"Celkem bylo prijato %02d bytu a %02d packetu.\n", sumPr, sumPrP); fprintf(f,"Server byl ukoncen.\n"); fprintf(f,"--------------------------------------------------\n"); fclose(f); printf("Server byl ukoncen.\n"); exit(0); } } } /* ____________________________________________________________________________ void *hlidani_spojeni(int *arg) Funkce vlakna, ktere hlida pripojovani klientu do her. ____________________________________________________________________________ */ void *hlidani_spojeni(int *arg){ //printf("arg : %d\n", *arg); int a2read, fd; fd_set tests, client_socks; int return_value; char cbuf[] = "z;"; int pocetBajtu; struct timeval tv; tv.tv_sec = 10; printf("Spusteno nove overovaci vlakno.\n"); FD_ZERO( &client_socks );// FD_SET(*arg, &client_socks); tests = client_socks; // sada deskriptoru je po kazdem volani select prepsana sadou deskriptoru kde se neco delo return_value = select(FD_SETSIZE, &client_socks, NULL, NULL, &tv); if (return_value < 0) { printf("Select - ERR\n"); exit(1); } // vynechavame stdin, stdout, stderr for( fd = 3; fd < FD_SETSIZE; fd++ ){ // je dany socket v sade fd ze kterych lze cist ? if( FD_ISSET( fd, &tests ) ){ // pocet bajtu co je pripraveno ke cteni ioctl( fd, FIONREAD, &a2read ); // mame co cist if (a2read >= 0){ pocetBajtu = send(*arg, cbuf, 2*sizeof(char),0); vypisSoubor(*arg,pocetBajtu, 3); FD_ZERO(&client_socks);// //printf("Tvuj souper se nepripojil do 10 sekund.\n"); pocetHracu = 0; } } } printf("Ukoncuju hlidaci vlakno!\n"); } /* ____________________________________________________________________________ int main (int argc, char *argv[]) Hlavni funkce serveru. Zde dochazi k pripojovani klientu do her, nacteni portu, zdali je zadany v parametru, vytvareni vlaken pro hry,... Nastaveni portu, na kterym ma server naslouchat. ____________________________________________________________________________ */ int main (int argc, char *argv[]){ int client_socket; int return_value; char cbuf[256]; int len_addr = 0; struct sockaddr_in my_addr, peer_addr; int argument = 0; HRA_S *hra; //deklarace vlakna pro overovani casu pripojeni pthread_t pthread; //deklarace vlakna pro hru pthread_t vlakno; //deklarace vlakna pro komunikaci se servrem pthread_t hlavniVlakno; pthread_create(&hlavniVlakno, NULL, (void *)&server, NULL); casGlob = time(NULL); struct tm *gloCas; gloCas = localtime(&casGlob); if(argc == 1){ argument = 10000; printf("Port je defaultne nastaven na: 10000.\n"); } else{ argument = atoi(argv[1]); if(argument > 1025 && argument < 65536){ printf("Server bezi na portu: %d\n",argument); }else{ printf("Zadali jste spatny port, je nastaven defaultne na: 10000.\n"); argument = 10000; } } int errorBind = 1; server_socket = socket(AF_INET, SOCK_STREAM, 0); setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &errorBind, sizeof(errorBind)); memset(&my_addr, 0, sizeof(struct sockaddr_in)); // nulovani pameti my_addr.sin_family = AF_INET; my_addr.sin_port = htons(argument); my_addr.sin_addr.s_addr = INADDR_ANY; return_value = bind(server_socket, (struct sockaddr *) &my_addr, \ sizeof(struct sockaddr_in)); if (return_value == 0) printf("Bind - OK\n"); else { printf("Bind - ERR\n"); return -1; } return_value = listen(server_socket, 5); if (return_value == 0) printf("Listen - OK\n"); else { printf("Listen - ERR\n"); return -1; } printf("Pocet hracu: %d\n",pocetHracu); //fprintf(f, "Server bezi na portu: %d.\n",argument); while(1){ client_socket = accept(server_socket, (struct sockaddr *) &peer_addr, &len_addr); if (client_socket>0) { printf("Hura nove spojeni\n"); if(pocetHracu == 0){ printf("Prvni hrac pripojen\n"); hra = (HRA_S*) malloc(sizeof(HRA_S)); hra->client_socket1 = client_socket; fprintf(f, "%02i:%02i:%02i - Client byl pripojen se socketem: %d.\n", gloCas->tm_hour, gloCas->tm_min, gloCas->tm_sec, hra->client_socket1); pthread_create(&pthread, NULL, (void *)&hlidani_spojeni, &hra->client_socket1); pocetHracu++; } else if(pocetHracu == 1){ printf("Druhy hrac pripojen\n"); hra->client_socket2 = client_socket; pthread_create(&vlakno, NULL, (void *)&aplikace, (void *)hra); fprintf(f, "%02i:%02i:%02i - Client byl pripojen se socketem: %d.\n", gloCas->tm_hour, gloCas->tm_min, gloCas->tm_sec,hra->client_socket2); pthread_cancel(pthread); pocetHracu = 0; //wind = 0; } } else { printf ("Brutal Fatal ERROR\n"); return -1; } } return 0; }