Разбор опций командной строки. — КиберПедия 

Папиллярные узоры пальцев рук - маркер спортивных способностей: дерматоглифические признаки формируются на 3-5 месяце беременности, не изменяются в течение жизни...

Своеобразие русской архитектуры: Основной материал – дерево – быстрота постройки, но недолговечность и необходимость деления...

Разбор опций командной строки.

2017-11-17 217
Разбор опций командной строки. 0.00 из 5.00 0 оценок
Заказать работу

Задание на курсовую работу.

1. Опишите правила игры и алгоритм проведения игровой ситуации «крестики-нолики» (3х3).

2. Разработайте протокол взаимодействия клиентской и серверной частей приложения при: создании новой игры, подключении игроков к ранее созданной игре, проведении игровой ситуации и завершении её. Заложите возможность диалога игроков в режиме чата (через контролирующий сервер).

3. Определите тип протокола, который будет использоваться для взаимодействия клиентов и сервера (TCP или UDP).

  1. С использованием библиотек MyTerm и BigChars, разработайте набор функций:

· printBoard (struct board), выводящую на экран рабочее поле игры. Каждая ячейка поля представляется "большим" символом, само поле объведено в рамку. Рисунки символов "крестик" и "нолик" хранятся в одном файле (два больших символа, один - крестик, другой — нолик).

· setBoardPos (struct board, int, int, enum tPosSign), устанавливающую в указанную позицию поля крестик или нолик

· getBoardPos (struct board, int, int, enum tPosSign *), возвращает значение указанной позиции поля игры (крестик или нолик).

· editBoard (struct board *, int *, int *), реализующую редактирование поля (в свобоное место устанавливается крестик (F5) или нолик (F6), на занятое место установить ничего нельзя) и возвращающую позицию установленного символа.

  1. Реализуйте программу-сервер
  2. Реализуйте программу-клиент

Правила игры.

Игроки по очереди ставят на свободные клетки поля 3х3 знаки (один всегда крестики, другой всегда нолики). Первый, выстроивший в ряд 3 своих фигур по вертикали, горизонтали или диагонали, выигрывает. Первый ход делает игрок, ставящий крестики.

Обычно по завершении партии выигравшая сторона зачёркивает чертой свои три знака (нолика или крестика), составляющих сплошной ряд.

Описание протокола.

В качестве протокола транспортного уровня был выбран TCP.

Сообщения Сервер → Клиент Описание
1 (тип int) список игроков ожидающих соперника, далее отправляется количество пунктов меню (тип int), а затем отправляется заявляемое количество элементов структуры struct menu_type struct menu_type { int id; char ip[MAX_CH_IP]; };
2 (тип int) подтверждение создания игры Отправляется клиенту, в случае если удалось создать игру (в противном случае отправляется -2)
3 (тип int) подтверждение подключения к игре Отправляется клиенту, в случае если удалось присоединиться игру (в противном случае отправляется -3)
4 (тип int) подключение соперника Отправляется клиенту создавшему игру, информирует о подключения противника
5 (тип int) сообщение, далее передается размер сообщения, и потом передается само сообщение Используется для обмены сообщениями между клиентами
6 (тип int) подтверждение дозволенности хода Используется для проверки занятости ячейки
7 (тип int) ход противника, после следуют координата хода по x и y (тип int) Передает координаты хода противника
8 (тип int) отключение соединения Информирует об отключении противника
9 (тип int) победа клиента Информирует о победе клиента
10 (тип int) поражение клиента Информирует о поражения клиента
11 (тип int) игра вничью Информирует об окончании игры вничью
Сообщения Клиент → Сервер Описание
1 (тип int) запрос на список игроков ожидающих соперника Запрос на список игроков ожидающих соперника
2 (тип int) запрос на создание игры Запрос на создание игры
3 (тип int) запрос на присоединение к игре, далее следует ID игры Запрос на присоединение к игре
4 (тип int) сообщение, далее передается размер сообщения, и потом передается само сообщение Используется для обмены сообщениями между клиентами
5 (тип int) ход клиента, после следуют координата хода по x и y (тип int) Информирует о ходе клиента
6 (тип int) отключение клиента Информирует об отключении клиента

Общая схема работы клиента.

 

 

 
 

 

 

 

 


Общая схема работы сервера.

 

 


Исходный код board.h

#include "myBigChars.h"

#include "myTerm.h"

#include <fcntl.h>

 

#define max_row 32

#define max_col 50

#define BG White

#define FG Black

#define FGV Red

#define FBG Blue

#define MAXLINE 128

#define MAX_CH_IP 25

 

struct menu_type

{

int id;

char ip[MAX_CH_IP];

};

 

typedef enum { EMPTY, CROSS, ZERO } tPosSign;

typedef tPosSign board[3][3];

bigchar zero,cross,nul;

 

extern int initic();

extern int printBoard (board,int,int);

extern void setBoardPos(board, int, int, tPosSign);

extern void getBoardPos (board, int, int, tPosSign *);

extern int editBoard (board *, int *, int *);

extern int menu (struct menu_type *, int, int, int, int);

extern int victory(board,tPosSign *,int *,int *);

extern void win_printBoard (tPosSign,int,int);

 

Исходный код board.c

#include "board.h"

#include "error.h"

 

int initic()

{

int f,n;

nul.a=nul.b=0;

error_1_return(f=open("zero", O_RDONLY),"Ошибка при открытие файла zero",-1);

error_1_return(bigcharread(f, &zero, 1, &n),"Ошибка при считывание символа zero",-1);

close(f);

error_1_return(f=open("cross", O_RDONLY),"Ошибка при открытие файла cross",-1);

error_1_return(bigcharread(f, &cross, 1, &n),"Ошибка при считывание символа cross",-1);

close(f);

return 0;

}

 

int printBoard (board cletka,int x,int y)

{

int i,j;

bigchar bc;

getscreensize(&i,&j);

if (i<max_row || j<max_col)

{

printf("Ошибка: недостаточный размер экрана\n");

return -1;

}

setfgcolor(FG);

setbgcolor(BG);

box(1,1,30,30);

for (i=0;i<3;i++)

for (j=0;j<3;j++)

{

if (x==j&&y==i)

{

setfgcolor(FGV);

setbgcolor(BG);

}

else

{

setfgcolor(FG);

setbgcolor(BG);

}

box(2+j*10,2+i*10,8,8);

switch (cletka[i][j])

{

case ZERO:

bc=zero;

break;

case CROSS:

bc=cross;

break;

case EMPTY:

bc=nul;

break;

}

printbigchar(&bc,3+j*10,3+i*10,FG,BG);

}

return 0;

}

 

void setBoardPos(board cletka, int x, int y, tPosSign sign)

{

cletka[y][x] = sign;

bigchar bc;

switch (sign)

{

case ZERO:

bc=zero;

break;

case CROSS:

bc=cross;

break;

case EMPTY:

bc=nul;

break;

}

}

 

void getBoardPos(board cletka, int x, int y, tPosSign *sign)

{

*sign = cletka[y][x];

}

 

void edit_str(char str[], int x, int y,int wid)

{

int i;

gotoXY(x,y);

mywrite("%s",str);

for (i=strlen(str);i<wid;i++)

mywrite(" ");

}

 

int menu (struct menu_type *lst, int x, int y, int str,int wid)

{

int ed=0,i;

keys key;

clrscr();

setfgcolor(FGV);

setbgcolor(BG);

box(x,y,wid,str);

setfgcolor(FGV);

setbgcolor(FBG);

edit_str(lst[0].ip,x+1,y+1,wid);

setfgcolor(FG);

setbgcolor(BG);

for (i=1;i<str;i++)

edit_str(lst[i].ip,x+1,y+1+i,wid);

while (key!=K_ENTER && key!=K_ESC)

{

readkey(&key);

switch (key)

{

case K_DOWN:

setfgcolor(FG);

setbgcolor(BG);

edit_str(lst[ed].ip,x+1,y+1+ed,wid);

if (ed==str-1)

ed=0;

else

ed++;

setfgcolor(FGV);

setbgcolor(FBG);

edit_str(lst[ed].ip,x+1,y+1+ed,wid);

break;

case K_UP:

setfgcolor(FG);

setbgcolor(BG);

edit_str(lst[ed].ip,x+1,y+1+ed,wid);

if (ed==0)

ed=str-1;

else

ed--;

setfgcolor(FGV);

setbgcolor(FBG);

edit_str(lst[ed].ip,x+1,y+1+ed,wid);

break;

default:

break;

}

}

setfgcolor(FG);

setbgcolor(BG);

if (key==K_ESC)

return -1;

else

return ed;

}

 

int victory(board cletka,tPosSign *sign,int *napr,int *nom)

{

int i,j,k;

for (i=0;i<3;i++)

{

k=0;

for (j=1;j<3;j++)

if (cletka[i][j]==cletka[i][j-1]) k++;

if (k==2&&cletka[i][0]!=EMPTY)

{

*sign=cletka[i][0];

*napr=0;

*nom=i;

return 1;

}

}

for (j=0;j<3;j++)

{

k=0;

for (i=1;i<3;i++)

if (cletka[i][j]==cletka[i-1][j]) k++;

if (k==2&&cletka[0][j]!=EMPTY)

{

*sign=cletka[0][j];

*napr=1;

*nom=j;

return 1;

}

}

k=0;

for (i=1;i<3;i++)

if (cletka[i][i]==cletka[i-1][i-1]) k++;

if (k==2&&cletka[0][0]!=EMPTY)

{

*sign=cletka[0][0];

*napr=2;

*nom=0;

return 1;

}

k=0;

for (i=1;i<3;i++)

if (cletka[i][2-i]==cletka[i-1][3-i]) k++;

if (k==2&&cletka[0][2]!=EMPTY)

{

*sign=cletka[0][2];

*napr=2;

*nom=1;

return 1;

}

return 0;

}

 

void win_printBoard (tPosSign sign,int napr,int nom)

{

int i;

setfgcolor(FGV);

setbgcolor(BG);

switch (napr)

{

case 0:

for (i=0;i<3;i++)

box(2+i*10,2+nom*10,8,8);

break;

case 1:

for (i=0;i<3;i++)

box(2+nom*10,2+i*10,8,8);

break;

case 2:

if (nom)

{

box(2+2*10,2+0*10,8,8);

box(2+1*10,2+1*10,8,8);

box(2+0*10,2+2*10,8,8);

}

else

{

box(2+0*10,2+0*10,8,8);

box(2+1*10,2+1*10,8,8);

box(2+2*10,2+2*10,8,8);

}

break;

}

gotoXY(40,2);

if (sign==CROSS)

printf("CROSS WIN");

else

printf("ZERO WIN");

}

Исходный код 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;

}

Исходный код server.c

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <getopt.h>

#include <sys/time.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <errno.h>

#include <string.h>

#include <unistd.h>

#include <fcntl.h>

#include <pthread.h>

#include <time.h>

#include "board.h"

#include "error.h"

 

struct games_info{

char ch_ip1[MAX_CH_IP],ch_ip2[MAX_CH_IP],bufer[MAXLINE];

int connfd1,connfd2,id,mtx1,mtx2,oc,x,y,b;

pthread_mutex_t mutex1,mutex2;

board cletka;

} *games;

 

struct client_info

{

char ch_ip[MAX_CH_IP];

int connfd;

};

 

int listenfd,connfd,max_count_game=1,n_port=7777,ID=1;

static pthread_mutex_t mutex_list_games;

 

int com_str(int argc, char **argv,int *cg,int *pr)

{

const char* short_options = "g:p:";

const struct option long_options[] =

{

{"count-games",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 'g':

{

if (optarg!=NULL)

{

*cg=atoi(optarg);

if (*cg<=0)

{

printf("chisl\n");

return -1;

}

}

break;

}

case 201:

case 'p':

{

if (optarg!=NULL)

{

*pr=atoi(optarg);

if (*pr<=0)

{

printf("chisl\n");

return -1;

}

}

break;

}

}

}

return 0;

}

 

void creat_list(struct menu_type mas[],int *kol)

{

int i=1,k=0;

char pnkt1[]="Создать игру\0",pnkt2[]="Обновление списка\0";

pthread_mutex_lock(&mutex_list_games);

mas[k].id=-1;

strncpy(mas[k].ip,pnkt1,MAX_CH_IP);

k=1;

for (i=0;i<max_count_game;i++)

if (games[i].connfd1!=-1&&games[i].connfd2==-1)

{

strcpy(mas[k].ip,games[i].ch_ip1);

mas[k].id=games[i].id;

 

k++;

}

mas[k].id=-2;

strncpy(mas[k].ip,pnkt2,MAX_CH_IP);

*kol=k;

pthread_mutex_unlock(&mutex_list_games);

}

 

void *work_with_client(void *arg)

{

struct client_info *inf=(struct client_info *) arg;

int g,k,n,ot,b=1,t,oc,i,j,hod=0;

struct menu_type *mas;

fd_set readset;

struct timeval timeout;

mas=calloc(max_count_game+2,sizeof(struct menu_type));

creat_list(mas,&k);

k++;

error_pol_return(write(inf->connfd,&k,sizeof(int)),"Error",0);

error_pol_return(write(inf->connfd,mas,sizeof(struct menu_type)*k),"Error",0);

while (b)

{

error_pol_return(read(inf->connfd,&ot,sizeof(ot)),"Error",0);

switch (ot)

{

case 1://zapros

creat_list(mas,&k);

k++;

error_pol_return(write(inf->connfd,&k,sizeof(k)),"Error",0);

error_pol_return(write(inf->connfd,mas,sizeof(struct menu_type)*k),"Error",0);

break;

case 2://creat game

pthread_mutex_lock(&mutex_list_games);

for (i=0;i<max_count_game;i++)

if (games[i].connfd1==-1&&games[i].connfd2==-1)

{

g=i;

pthread_mutex_unlock(&games[g].mutex1);

pthread_mutex_unlock(&games[g].mutex2);

t=2;

error_pol_return(write(inf->connfd,&t,sizeof(int)),"Error",0);

t=g+1;

error_pol_return(write(inf->connfd,&t,sizeof(int)),"Error",0);

b=0;

games[i].id=ID++;

oc=1;

games[i].connfd1=inf->connfd;

games[g].mtx1=games[g].mtx2=0;

strcpy(games[i].ch_ip1,inf->ch_ip);

printf("Клиент %s создал игру\n",inf->ch_ip);

break;

}

pthread_mutex_unlock(&mutex_list_games);

if (i==max_count_game)

{

t=-2;

error_pol_return(write(inf->connfd,&t,sizeof(int)),"Error",0);

}

break;

case 3://connect game

error_pol_return(read(inf->connfd,&ot,sizeof(ot)),"Error",0);

pthread_mutex_lock(&mutex_list_games);

for (i=0;i<max_count_game;i++)

if (games[i].id==ot)

{

if (games[i].connfd2==-1)

{

games[i].connfd2=inf->connfd;

strcpy(games[i].ch_ip2,inf->ch_ip);

b=0;

oc=2;

games[i].oc=2;

g=i;

t=3;

error_pol_return(write(inf->connfd,&t,sizeof(int)),"Error",0);

pthread_mutex_lock(&games[g].mutex1);

games[g].mtx1=1;

pthread_mutex_unlock(&games[g].mutex1);

printf("Клиент %s подключился к игре %s\n",inf->ch_ip,games[i].ch_ip1);

}

else

{

t=-3;

error_pol_return(write(inf->connfd,&t,sizeof(int)),"Error",0);

}

break;

}

pthread_mutex_unlock(&mutex_list_games);

break;

case 6://disconnect

printf("Клиент %s отключился\n",inf->ch_ip);

return 0;

}

}

if (oc==1)

{

while (1)

{

errno=0;

fcntl(inf->connfd, F_SETFL, FNDELAY|fcntl(inf->connfd, F_GETFL, 0));

n=read(inf->connfd,&ot,sizeof(ot));

fcntl(inf->connfd, F_SETFL, ~FNDELAY&fcntl(inf->connfd, F_GETFL, 0));

if (errno!=11) goto the_end;

if (n>0&&ot==6)

{

printf("Клиент %s отключился\n",inf->ch_ip);

pthread_mutex_lock(&mutex_list_games);

games[g].connfd1=-1;

pthread_mutex_unlock(&mutex_list_games);

goto the_end;

}

pthread_mutex_lock(&games[g].mutex1);

if (games[g].mtx1==1)

{

t=4;

error_pol_return(write(inf->connfd,&t,sizeof(int)),"Error",0);

games[g].mtx1=0;

games[g].oc=1;

pthread_mutex_unlock(&games[g].mutex1);

break;

}

pthread_mutex_unlock(&games[g].mutex1);

}

}

for (i=0;i<2;i++)

for (j=0;j<2;j++)

games[g].cletka[i][j]=EMPTY;

games[g].mtx2=0;

while (1)

{

FD_ZERO(&readset);

FD_SET(inf->connfd,&readset);

timeout.tv_sec=0;

timeout.tv_usec=500;

fcntl(inf->connfd, F_SETFL, FNDELAY|fcntl(inf->connfd, F_GETFL, 0));

n=select(inf->connfd+1, &readset, NULL, NULL, &timeout);

fcntl(inf->connfd, F_SETFL, ~FNDELAY&fcntl(inf->connfd, F_GETFL, 0));

if (n>0)

{

read(inf->connfd,&ot,sizeof(ot));

switch (ot)

{

case 4://text

error_1_goto(read(inf->connfd,&t,sizeof(int)),"Error",the_end);

error_1_goto(read(inf->connfd,&games[g].bufer,t),"Error",the_end);

games[g].bufer[t]='\0';

if (oc==1)

{

pthread_mutex_lock(&games[g].mutex2);

games[g].mtx2=2;

pthread_mutex_unlock(&games[g].mutex2);

}

else

{

pthread_mutex_lock(&games[g].mutex1);

games[g].mtx1=2;

pthread_mutex_unlock(&games[g].mutex1);

}

break;

case 5://hod

if (games[g].oc==oc)

{

error_1_goto(read(inf->connfd,&t,sizeof(int)),"Error",the_end);

games[g].x=t;

error_1_goto(read(inf->connfd,&t,sizeof(int)),"Error",the_end);

games[g].y=t;

if (games[g].cletka[games[g].y][games[g].x]==EMPTY)

{

if (games[g].oc==1)

games[g].cletka[games[g].y][games[g].x]=CROSS;

else

games[g].cletka[games[g].y][games[g].x]=ZERO;

t=6;

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error",the_end);

if (oc==1)

{

hod++;

pthread_mutex_lock(&games[g].mutex2);

games[g].oc=2;

games[g].mtx2=3;

pthread_mutex_unlock(&games[g].mutex2);

}

else

{

pthread_mutex_lock(&games[g].mutex1);

games[g].oc=1;

games[g].mtx1=3;

pthread_mutex_unlock(&games[g].mutex1);

}

tPosSign sign;

if (victory(games[g].cletka,&sign,&t,&t))

{

if (games[g].oc==2)

printf("Клиент %s победил %s\n",games[g].ch_ip1,games[g].ch_ip2);

else

printf("Клиент %s победил %s\n",games[g].ch_ip2,games[g].ch_ip1);

if (sign==CROSS)

{

t=9;

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error",the_end);

pthread_mutex_lock(&games[g].mutex2);

games[g].mtx2=4;

pthread_mutex_unlock(&games[g].mutex2);

goto the_end;

}

else

{

t=9;

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error",the_end);

pthread_mutex_lock(&games[g].mutex1);

games[g].mtx1=4;

pthread_mutex_unlock(&games[g].mutex1);

goto the_end;

}

goto the_end;

}

else

if (hod==5)

{

printf("Клиенты %s,%s сыграли вничью\n",games[g].ch_ip1,games[g].ch_ip2);

t=11;

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error",the_end);

pthread_mutex_lock(&games[g].mutex2);

games[g].mtx2=6;

pthread_mutex_unlock(&games[g].mutex2);

goto the_end;

}

}

else

{

t=-6;

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error",the_end);

}

}

break;

case 6://disconnect

if (oc==1)

{

pthread_mutex_lock(&games[g].mutex2);

games[g].mtx2=5;

pthread_mutex_unlock(&games[g].mutex2);

}

else

{

pthread_mutex_lock(&games[g].mutex1);

games[g].mtx1=5;

pthread_mutex_unlock(&games[g].mutex1);

}

goto the_end;

break;

}

}

if (oc==1)

{

pthread_mutex_lock(&games[g].mutex1);

if (games[g].mtx1!=0)

{

switch (games[g].mtx1)

{

case 2://text

t=5;

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error",the_end);

t=strlen(games[g].bufer);

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error",the_end);

error_pol_goto(write(inf->connfd,&games[g].bufer,t),"Error",the_end);

break;

case 3://hod prot

t=7;

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error",the_end);

error_pol_goto(write(inf->connfd,&games[g].x,sizeof(int)),"Error",the_end);

error_pol_goto(write(inf->connfd,&games[g].y,sizeof(int)),"Error",the_end);

break;

case 4://fail

t=10;

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error",the_end);

goto the_end;

break;

case 5://disconnect

t=8;

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error",the_end);

goto the_end;

break;

case 6://nichia

t=11;

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error",the_end);

goto the_end;

break;

}

}

games[g].mtx1=0;

pthread_mutex_unlock(&games[g].mutex1);

}

else

{

pthread_mutex_lock(&games[g].mutex2);

if (games[g].mtx2!=0)

{

switch (games[g].mtx2)

{

case 2://text

t=5;

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error1",the_end);

t=strlen(games[g].bufer);

games[g].bufer[t]='\0';

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error2",the_end);

error_pol_goto(write(inf->connfd,&games[g].bufer,t),"Error3",the_end);

break;

case 3://hod prot

t=7;

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error",the_end);

error_pol_goto(write(inf->connfd,&games[g].x,sizeof(int)),"Error",the_end);

error_pol_goto(write(inf->connfd,&games[g].y,sizeof(int)),"Error",the_end);

break;

case 4://fail

t=10;

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error",the_end);

goto the_end;

break;

case 5://fail

t=8;

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error",the_end);

goto the_end;

break;

case 6://nichia

t=11;

error_pol_goto(write(inf->connfd,&t,sizeof(int)),"Error",the_end);

goto the_end;

break;

}

}

games[g].mtx2=0;

pthread_mutex_unlock(&games[g].mutex2);

}

}

the_end:;

if (oc==1)

{

t=8;

printf("Клиент %s отключился\n",games[g].ch_ip1);

write(games[g].connfd1,&t,sizeof(int));

if (games[g].connfd1!=-1)

close(games[g].connfd1);

pthread_mutex_lock(&mutex_list_games);

games[g].connfd1=-1;

pthread_mutex_unlock(&mutex_list_games);

games[g].mtx1=0;

b=1;

while (b)

{

pthread_mutex_lock(&games[g].mutex2);

if (games[g].mtx2==0) b=0;

pthread_mutex_unlock(&games[g].mutex2);

}

pthread_mutex_lock(&games[g].mutex2);

games[g].mtx2=5;

pthread_mutex_unlock(&games[g].mutex2);

return 0;

}

else

{

t=8;

printf("Клиент %s отключился\n",games[g].ch_ip2);

write(games[g].connfd2,&t,sizeof(int));

if (games[g].connfd2!=-1)

close(games[g].connfd2);

pthread_mutex_lock(&mutex_list_games);

games[g].connfd2=-1;

pthread_mutex_unlock(&mutex_list_games);

games[g].mtx2=0;

b=1;

while (b)

{

pthread_mutex_lock(&games[g].mutex1);

if (games[g].mtx1==0) b=0;

pthread_mutex_unlock(&games[g].mutex1);

}

pthread_mutex_lock(&games[g].mutex1);

games[g].mtx1=5;

pthread_mutex_unlock(&games[g].mutex1);

return 0;

}

}

 

int main(int argc, char **argv)

{

unsigned int len;

struct client_info *temp;

struct sockaddr_in servaddr,clnaddr;

char adr[15]/*,port[5]*/;

pthread_t tid;

int i;

com_str(argc,argv,&max_count_game,&n_port);

if (max_count_game<1)

{

printf("Error count game\n");

return -1;

}

error_0_return(games=calloc(max_count_game,sizeof(struct games_info)),"Memory",-1);

for (i=0;i<max_count_game;i++)

{

pthread_mutex_init(&games[i].mutex1,NULL);

pthread_mutex_init(&games[i].mutex2,NULL);

games[i].connfd1=games[i].connfd2=-1;

games[i].mtx1=games[i].mtx2=0;

}

listenfd=socket(AF_INET,SOCK_STREAM,0);

bzero(&servaddr,sizeof(servaddr));

servaddr.sin_family=AF_INET;

servaddr.sin_addr.s_addr=htonl(INADDR_ANY);

servaddr.sin_port=htons(n_port);

error_1_return(bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr))," ",-1);

error_1_return(listen(listenfd, 1)," ",-1);

len=sizeof(clnaddr);

pthread_mutex_init(&mutex_list_games,NULL);

while (1)

{

error_1_continue(connfd=accept(listenfd,(struct sockaddr *) &clnaddr,&len)," ");

temp=malloc(sizeof(struct client_info));

inet_ntop(AF_INET,(struct sockaddr *) &clnaddr.sin_addr.s_addr, adr, 15);

snprintf(temp->ch_ip,MAX_CH_IP,"%s:%d",adr,ntohs(clnaddr.sin_port));

printf("Клиент %s присоединился\n",temp->ch_ip);

temp->connfd=connfd;

error_no0_continue(pthread_create(&tid,NULL,work_with_client,(void *)temp),"Error potok");

}

close(connfd);

return 0;

}

Задание на курсовую работу.

1. Опишите правила игры и алгоритм проведения игровой ситуации «крестики-нолики» (3х3).

2. Разработайте протокол взаимодействия клиентской и серверной частей приложения при: создании новой игры, подключении игроков к ранее созданной игре, проведении игровой ситуации и завершении её. Заложите возможность диалога игроков в режиме чата (через контролирующий сервер).

3. Определите тип протокола, который будет использоваться для взаимодействия клиентов и сервера (TCP или UDP).

  1. С использованием библиотек MyTerm и BigChars, разработайте набор функций:

· printBoard (struct board), выводящую на экран рабочее поле игры. Каждая ячейка поля представляется "большим" символом, само поле объведено в рамку. Рисунки символов "крестик" и "нолик" хранятся в одном файле (два больших символа, один - крестик, другой — нолик).

· setBoardPos (struct board, int, int, enum tPosSign), устанавливающую в указанную позицию поля крестик или нолик

· getBoardPos (struct board, int, int, enum tPosSign *), возвращает значение указанной позиции поля игры (крестик или нолик).

· editBoard (struct board *, int *, int *), реализующую редактирование поля (в свобоное место устанавливается крестик (F5) или нолик (F6), на занятое место установить ничего нельзя) и возвращающую позицию установленного символа.

  1. Реализуйте программу-сервер
  2. Реализуйте программу-клиент

Правила игры.

Игроки по очереди ставят на свободные клетки поля 3х3 знаки (один всегда крестики, другой всегда нолики). Первый, выстроивший в ряд 3 своих фигур по вертикали, горизонтали или диагонали, выигрывает. Первый ход делает игрок, ставящий крестики.

Обычно по завершении партии выигравшая сторона зачёркивает чертой свои три знака (нолика или крестика), составляющих сплошной ряд.

Описание протокола.

В качестве протокола транспортного уровня был выбран TCP.

Сообщения Сервер → Клиент Описание
1 (тип int) список игроков ожидающих соперника, далее отправляется количество пунктов меню (тип int), а затем отправляется заявляемое количество элементов структуры struct menu_type struct menu_type { int id; char ip[MAX_CH_IP]; };
2 (тип int) подтверждение создания игры Отправляется клиенту, в случае если удалось создать игру (в противном случае отправляется -2)
3 (тип int) подтверждение подключения к игре Отправляется клиенту, в случае если удалось присоединиться игру (в противном случае отправляется -3)
4 (тип int) подключение соперника Отправляется клиенту создавшему игру, информирует о подключения противника
5 (тип int) сообщение, далее передается размер сообщения, и потом передается само сообщение Используется для обмены сообщениями между клиентами
6 (тип int) подтверждение дозволенности хода Используется для проверки занятости ячейки
7 (тип int) ход противника, после следуют координата хода по x и y (тип int) Передает координаты хода противника
8 (тип int) отключение соединения Информирует об отключении противника
9 (тип int) победа клиента Информирует о победе клиента
10 (тип int) поражение клиента Информирует о поражения клиента
11 (тип int) игра вничью Информирует об окончании игры вничью
Сообщения Клиент → Сервер Описание
1 (тип int) запрос на список игроков ожидающих соперника Запрос на список игроков ожидающих соперника
2 (тип int) запрос на создание игры Запрос на создание игры
3 (тип int) запрос на присоединение к игре, далее следует ID игры Запрос на присоединение к игре
4 (тип int) сообщение, далее передается размер сообщения, и потом передается само сообщение Используется для обмены сообщениями между клиентами
5 (тип int) ход клиента, после следуют координата хода по x и y (тип int) Информирует о ходе клиента
6 (тип int) отключение клиента Информирует об отключении клиента

Общая схема работы клиента.

 

 

 
 

 

 

 

 


Общая схема работы сервера.

 

 


Разбор опций командной строки.

Клиент и сервер при запуске начинают разбор опций командной строки при помощи функции библиотеки getopt.h: getopt_long.

Описание опций клиента:

-s или --game-server — задаёт IP адрес сервера (по умолчанию 127.0.0.1)

-p или --game-server-port — задаёт номер порта для подключения (по умолчанию 7777)

Описание опций сервера:

-g или --count-games — задаёт количество игр (по умолчанию 1)

-p или --game-server-port — задаёт порт для прослушивания (по умолчанию 7777)

Код разбора опций для клиента представлен ниже. Для сервера код аналогичен.

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;

}

Здесь происходит установка глобальных переменных ip_serv и n_port, проверка допустимости введённых значений. Если обнаружена недопустимая опция или другая ошибка при разборе, будет выведено сообщение по правильному использованию и произойдёт выход из программы.


Поделиться с друзьями:

Эмиссия газов от очистных сооружений канализации: В последние годы внимание мирового сообщества сосредоточено на экологических проблемах...

Особенности сооружения опор в сложных условиях: Сооружение ВЛ в районах с суровыми климатическими и тяжелыми геологическими условиями...

Индивидуальные и групповые автопоилки: для животных. Схемы и конструкции...

Кормораздатчик мобильный электрифицированный: схема и процесс работы устройства...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

1.052 с.