- •Задание на курсовую работу.
- •Правила игры.
- •Описание протокола.
- •Общая схема работы клиента.
- •Общая схема работы сервера.
- •Разбор опций командной строки.
- •Описание реализации протокола на сервере.
- •Описание реализации протокола на клиенте.
- •Описание пользовательского интерфейса клиента.
- •Исходный код board.H
- •Исходный код board.C
- •Исходный код client.C
- •Исходный код server.C
Общая схема работы клиента.
Нет
Нет
Да
Да
Общая схема работы сервера.
Да
Нет
Нет
Да
Ожидание второго
игрока
Разбор опций командной строки.
Клиент и сервер при запуске начинают разбор опций командной строки при помощи функции библиотеки 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, проверка допустимости введённых значений. Если обнаружена недопустимая опция или другая ошибка при разборе, будет выведено сообщение по правильному использованию и произойдёт выход из программы.
Описание реализации протокола на сервере.
После создания прослушивающего сокета, сервер входит в цикл приёма соединения:
В случае если происходит подключение нового клиента, выполняется тело цикла, в котором необходимо записать информацию о клиенте (дескриптор и IP адрес) в буфер, запустить отдельную нить для дальнейшего диалога с клиентом, передав указатель на данный буфер.
Работа нити, обрабатывающая клиента, начинается с отправки списка клиентов ожидающих подключения второго игрока
Далее ожидается сообщения от клиента о создании игры или подключения игре. Клиент создавший игру становится хозяином игры (и первый начинает ходить), а подключившийся — вторым игроком.
После получения запроса на игру в глобальном массиве games[] резервируется первый свободный элемент (признак свободности поля connfd1 и connfd2 равны -1). Для защиты от одновременного доступа к этой переменной, также используется мьютекс mutex_list_games.
Если же принят запрос на подключения, то ищется игра по ID переданному от клиента если к данной игре не подключился другой клиент, то игра полностью резервируется.
Далее в цикле с неблокируемым вводом обрабатываются запросы от клиента, и сообщения от нити обслуживающую клиента-противника. Здесь передается сообщения чата, ходы и информация о отключения клиента. Сообщения между нитями передаются через “переменные состояния” (mtx1 и mtx2), безопасность данного взаимодействия обеспечивается мьютексами
По завершении главного цикла, игрокам отправляются сообщения о победителе или об игре вничью и процесс завершается.