- •Задание на курсовую работу.
- •Правила игры.
- •Описание протокола.
- •Общая схема работы клиента.
- •Общая схема работы сервера.
- •Разбор опций командной строки.
- •Описание реализации протокола на сервере.
- •Описание реализации протокола на клиенте.
- •Описание пользовательского интерфейса клиента.
- •Исходный код board.H
- •Исходный код board.C
- •Исходный код client.C
- •Исходный код server.C
Исходный код client.C
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include "board.h"
#include "error.h"
#define max_mes 27
int x=0,y=0,maxx,maxy,mtx1=0,mtx2=0,hx,hy,och,reg=1,i,kol_mes=0,prin[max_mes];
char buffer[MAX_CH_IP],message[max_mes][MAXLINE];
pthread_mutex_t mutex1,mutex2;
board cletka={{EMPTY,EMPTY,EMPTY},{EMPTY,EMPTY,EMPTY},{EMPTY,EMPTY,EMPTY}};
tPosSign sign,sign_cl;
int com_str(int argc, char **argv,char ip[],int *pr)
{
const char* short_options = "s:p:";
const struct option long_options[] =
{
{"game-server",required_argument,NULL,200},
{"game-server-port",required_argument,NULL,201},
{NULL,0,NULL,0}
};
int rez;
int option_index;
while ((rez=getopt_long(argc,argv,short_options,long_options,&option_index))!=-1)
{
switch(rez)
{
case 200:
case 's':
{
strcpy(ip,optarg);
break;
}
case 201:
case 'p':
{
if (optarg!=NULL)
{
*pr=atoi(optarg);
if (*pr<=0)
{
printf("chisl\n");
return -1;
}
}
break;
}
}
}
return 0;
}
int ris()
{
int i;
clrscr();
getscreensize(&maxy,&maxx);
if (maxy<32 || maxx<=54)
{
printf("Недостаточный размер окна\n");
mytermrestore();
setcursor(1);
exit(-1);
}
else
{
if (reg)
{
printBoard(cletka,x,y);
box(33,1,maxx-34,27);
box(33,30,maxx-34,1);
}
else
{
printBoard(cletka,-1,-1);
box(33,1,maxx-34,27);
setfgcolor(FGV);
box(33,30,maxx-34,1);
}
// mytermrestore();
setfgcolor(Magenta);
gotoXY(34,2);
write(OUTPUT_STREAM,message[0],strlen(message[0]));
for (i=1;i<max_mes;i++)
{
gotoXY(34,2+i);
if (prin[i])
{
setfgcolor(FGV);
write(OUTPUT_STREAM,message[i],strlen(message[i]));
}
else
{
setfgcolor(FG);
write(OUTPUT_STREAM,message[i],strlen(message[i]));
}
}
// mytermregime(0,0,1,0,1);
}
printBoard(cletka,x,y);
return 0;
}
void handler(int signo)
{
getscreensize(&y,&x);
ris();
}
void add_str(char *ch1,int pri)
{
int i;
if (kol_mes<max_mes)
{
kol_mes++;
strcpy(message[kol_mes],ch1);
prin[kol_mes]=pri;
}
else
{
for (i=1;i<max_mes-1;i++)
{
strcpy(message[kol_mes+1],message[kol_mes]);
prin[i]=prin[i+1];
}
strcpy(message[i],ch1);
prin[i]=pri;
}
}
void *con_ser(void *arg)
{
int des=(int)(int *) arg,n,ot,t,b;
while (1)
{
fcntl(des, F_SETFL, FNDELAY|fcntl(des, F_GETFL, 0));
n=read(des,&ot,sizeof(int));
fcntl(des, F_SETFL, ~FNDELAY&fcntl(des, F_GETFL, 0));
if (n<0 && errno!=11) goto the_end;
if (n>0)
{
switch (ot)
{
case 5://text
error_pol_goto(read(des,&t,sizeof(int)),"Error",the_end);
error_pol_goto(read(des,&buffer,t),"Error",the_end);
buffer[t]='\0';
b=1;
while (b)
{
pthread_mutex_lock(&mutex1);
if (mtx1==0) b=0;
pthread_mutex_unlock(&mutex1);
}
pthread_mutex_lock(&mutex1);
mtx1=8;
pthread_mutex_unlock(&mutex1);
break;
case 7:
error_pol_goto(read(des,&hx,sizeof(int)),"Error",the_end);
error_pol_goto(read(des,&hy,sizeof(int)),"Error",the_end);
b=1;
while (b)
{
pthread_mutex_lock(&mutex1);
if (mtx1==0) b=0;
pthread_mutex_unlock(&mutex1);
}
pthread_mutex_lock(&mutex1);
mtx1=3;
pthread_mutex_unlock(&mutex1);
break;
case 8:
b=1;
while (b)
{
pthread_mutex_lock(&mutex1);
if (mtx1==0) b=0;
pthread_mutex_unlock(&mutex1);
}
pthread_mutex_lock(&mutex1);
mtx1=4;
pthread_mutex_unlock(&mutex1);
break;
case 9:
b=1;
while (b)
{
pthread_mutex_lock(&mutex1);
if (mtx1==0) b=0;
pthread_mutex_unlock(&mutex1);
}
pthread_mutex_lock(&mutex1);
mtx1=5;
pthread_mutex_unlock(&mutex1);
break;
case 10:
b=1;
while (b)
{
pthread_mutex_lock(&mutex1);
if (mtx1==0) b=0;
pthread_mutex_unlock(&mutex1);
}
pthread_mutex_lock(&mutex1);
mtx1=6;
pthread_mutex_unlock(&mutex1);
break;
case 11:
b=1;
while (b)
{
pthread_mutex_lock(&mutex1);
if (mtx1==0) b=0;
pthread_mutex_unlock(&mutex1);
}
pthread_mutex_lock(&mutex1);
mtx1=7;
pthread_mutex_unlock(&mutex1);
break;
}
}
pthread_mutex_lock(&mutex2);
switch (mtx2)
{
case 1:
ot=5;
error_pol_goto(write(des,&ot,sizeof(int)),"Error",the_end);
error_pol_goto(write(des,&hx,sizeof(int)),"Error",the_end);
error_pol_goto(write(des,&hy,sizeof(int)),"Error",the_end);
error_pol_goto(read(des,&ot,sizeof(int)),"Error",the_end);
b=1;
while (b)
{
pthread_mutex_lock(&mutex1);
if (mtx1==0) b=0;
pthread_mutex_unlock(&mutex1);
}
if (ot==6)
{
pthread_mutex_lock(&mutex1);
mtx1=1;
pthread_mutex_unlock(&mutex1);
}
mtx2=0;
och=0;
break;
case 2:
ot=6;
write(des,&ot,sizeof(int));
mtx2=0;
pthread_mutex_lock(&mutex1);
mtx1=2;
pthread_mutex_unlock(&mutex1);
break;
case 3:
ot=4;
error_pol_goto(write(des,&ot,sizeof(int)),"Error",the_end);
ot=strlen(buffer)-1;
error_pol_goto(write(des,&ot,sizeof(int)),"Error",the_end);
error_pol_goto(write(des,buffer,ot),"Error",the_end);
mtx2=0;
break;
}
pthread_mutex_unlock(&mutex2);
}
the_end:;
pthread_mutex_lock(&mutex1);
mtx1=4;
pthread_mutex_unlock(&mutex1);
return 0;
}
int main(int argc, char **argv)
{
char ip_serv[15],ch;
int n_port=7777,sockfd,n,k_list,pn,t,b;
struct sockaddr_in servaddr;
struct menu_type *list;
pthread_t tid;
keys k;
if (initic()==-1)
return -1;
getscreensize(&maxy,&maxx);
signal(SIGWINCH,handler);
strcpy(ip_serv,"127.0.0.1\0");
com_str(argc,argv,ip_serv,&n_port);
error_1_return(sockfd = socket(AF_INET, SOCK_STREAM, 0)," ",-1);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(n_port);
error_pol_return(inet_pton(AF_INET,ip_serv,&servaddr.sin_addr)," ",-1);
error_1_return(connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr))," ",-1);
read(sockfd,&k_list,sizeof(int));
list=calloc(k_list,sizeof(struct menu_type));
read(sockfd,list,k_list*sizeof(struct menu_type));
strncpy(list[0].ip,"Создать игру\0",MAX_CH_IP);
strcpy(list[k_list-1].ip,"Обновление списка\0");
mytermsave();
mytermregime(0, 0, 1, 0, 1);
setcursor(0);
if (maxy<=32 || maxx<=54)
{
mytermrestore();
setcursor(1);
printf("Недостаточный размер окна\n");
return -1;
}
while (1)
{
pn=menu(list,(int)maxx/2-MAX_CH_IP/2-1,(int)maxy/2-k_list/2-1,k_list,MAX_CH_IP);
if (pn==-1)
{
t=6;
write(sockfd,&t,sizeof(int));
close(sockfd);
clrscr();
mytermrestore();
setcursor(1);
return 0;
}
if (pn==0)
{
t=2;
write(sockfd,&t,sizeof(int));
read(sockfd,&t,sizeof(int));
if (t==2)
{
clrscr();
och=1;
read(sockfd,&t,sizeof(int));
printf("Игра %d созданна, ожидание второго игрока\n",t);
break;
}
else
{
clrscr();
printf("Ошибка, игра не созданна\n");
readkey(&k);
continue;
}
}
if (pn==k_list-1)
{
t=1;
write(sockfd,&t,sizeof(int));
read(sockfd,&k_list,sizeof(int));
list=realloc(list,k_list*sizeof(struct menu_type));
read(sockfd,list,k_list*sizeof(struct menu_type));
strncpy(list[0].ip,"Создать игру\0",MAX_CH_IP);
strcpy(list[k_list-1].ip,"Обновление списка\0");
continue;
}
t=3;
write(sockfd,&t,sizeof(int));
write(sockfd,&list[pn].id,sizeof(int));
n=read(sockfd,&t,sizeof(int));
if (t==3)
{
och=0;
break;
}
else
{
clrscr();
printf("Ошибка присоединения к игре\n");
readkey(&k);
continue;
}
}
mytermrestore();
setcursor(1);
if (och)
{
read(sockfd,&t,sizeof(int));
if (t!=4)
{
clrscr();
printf("Ошибка\n");
mytermrestore();
setcursor(1);
return -1;
}
strcpy(message[0],"ваш ход\0");
sign_cl=CROSS;
}
else
{
sign_cl=ZERO;
strcpy(message[0],"ожидание хода противника\0");
}
clrscr();
mytermsave();
mytermregime(0,5,0,0,1);
setcursor(0);
ris();
pthread_mutex_init(&mutex1,NULL);
pthread_mutex_init(&mutex2,NULL);
error_no0_return(pthread_create(&tid,NULL,con_ser,(void *)sockfd),"Error potok",-1);
while (1)
{
mytermregime(0,5,0,0,1);
n=Readkey(&k,&ch);
if (n==1)
switch (k)
{
case K_UP:
if (y > 0)
{
--y;
printBoard(cletka,x,y);
}
break;
case K_DOWN:
if (y < 2)
{
++y;
printBoard(cletka,x,y);
}
break;
case K_LEFT:
if (x > 0)
{
--x;
printBoard(cletka,x,y);
}
break;
case K_RIGHT:
if (x < 2)
{
++x;
printBoard(cletka,x,y);
}
break;
case K_F6:
reg=0;
ris();
read(INPUT_STREAM,buffer,MAXLINE);
gotoXY(35,31);
mytermregime(1,0,0,1,1);
setcursor(1);
if (read(INPUT_STREAM,buffer,MAXLINE)!=0)
{
b=1;
while (b)
{
pthread_mutex_lock(&mutex2);
if (mtx2==0) b=0;
pthread_mutex_unlock(&mutex2);
}
pthread_mutex_lock(&mutex2);
mtx2=3;
pthread_mutex_unlock(&mutex2);
add_str(buffer,1);
}
mytermregime(0,5,0,0,1);
setcursor(0);
reg=1;
ris();
break;
case K_ESC:
b=1;
while (b)
{
pthread_mutex_lock(&mutex2);
if (mtx2==0) b=0;
pthread_mutex_unlock(&mutex2);
}
pthread_mutex_lock(&mutex2);
mtx2=2;
pthread_mutex_unlock(&mutex2);
break;
case K_ENTER:
getBoardPos(cletka,x,y,&sign);
if (och&&sign==EMPTY)
{
b=1;
while (b)
{
pthread_mutex_lock(&mutex2);
if (mtx2==0) b=0;
pthread_mutex_unlock(&mutex2);
}
pthread_mutex_lock(&mutex2);
mtx2=1;
hx=x;
hy=y;
pthread_mutex_unlock(&mutex2);
}
default: break;
}
pthread_mutex_lock(&mutex1);
switch (mtx1)
{
case 1:
strcpy(message[0],"ожидание хода противника\0");
setBoardPos(cletka,hx,hy,sign_cl);
printBoard(cletka,x,y);
ris();
mtx1=0;
break;
case 2:
mtx1=0;
goto the_end;
break;
case 3:
if (sign_cl==CROSS)
setBoardPos(cletka,hx,hy,ZERO);
else
setBoardPos(cletka,hx,hy,CROSS);
strcpy(message[0],"ваш ход\0");
printBoard(cletka,x,y);
ris();
och=1;
mtx1=0;
break;
case 4:
mtx1=0;
pthread_mutex_unlock(&mutex1);
goto the_end;
break;
case 5:
mtx1=0;
strcpy(message[0],"вы победили\0");
ris();
mytermregime(0,0,1,0,1);
readkey(&k);
clrscr();
break;
case 6:
mtx1=0;
strcpy(message[0],"вы проиграли\0");
ris();
mytermregime(0,0,1,0,1);
readkey(&k);
clrscr();
break;
case 7:
mtx1=0;
strcpy(message[0],"выиграла дружба\0");
ris();
mytermregime(0,0,1,0,1);
readkey(&k);
clrscr();
break;
case 8:
mtx1=0;
add_str(buffer,0);
ris();
break;
}
pthread_mutex_unlock(&mutex1);
}
the_end:;
close(sockfd);
mytermrestore();
setcursor(1);
clrscr();
return 0;
}