Answer:
Step-by-step explanation:
minor4server.c:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int player_count = 0;
pthread_mutex_t mutexcount;
void error(const char *msg)
{
perror(msg);
pthread_exit(NULL);
}
/* Reads an int from a client socket. */
int recv_int(int cli_sockfd)
n != sizeof(int)) /* Client likely disconnected. */
return -1;
#ifdef DEBUG
printf("[DEBUG] Received int: %d\\", msg);
#endif
return msg;
/* Writes a message to a client socket. */
void write_client_msg(int cli_sockfd, char * msg)
{
int n = write(cli_sockfd, msg, strlen(msg));
if (n < 0)
error("ERROR writing msg to client socket");
}
/* Writes an int to a client socket. */
void write_client_int(int cli_sockfd, int msg)
{
int n = write(cli_sockfd, &msg, sizeof(int));
if (n < 0)
error("ERROR writing int to client socket");
}
/* Writes a message to both client sockets. */
void write_clients_msg(int * cli_sockfd, char * msg)
{
write_client_msg(cli_sockfd[0], msg);
write_client_msg(cli_sockfd[1], msg);
}
/* Writes an int to both client sockets. */
void write_clients_int(int * cli_sockfd, int msg)
{
write_client_int(cli_sockfd[0], msg);
write_client_int(cli_sockfd[1], msg);
}
/* Sets up the listener socket. */
int setup_listener(int portno)
{
int sockfd;
struct sockaddr_in serv_addr;
/* Get a socket to listen on */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening listener socket.");
/* Zero out the memory for the server information */
memset(&serv_addr, 0, sizeof(serv_addr));
/* set up the server info */
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Bind the server info to the listener socket. */
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR binding listener socket.");
#ifdef DEBUG
printf("[DEBUG] Listener set.\\");
#endif
/* Return the socket number. */
return sockfd;
}
/* Sets up the client sockets and client connections. */
void get_clients(int lis_sockfd, int * cli_sockfd)
{
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
#ifdef DEBUG
printf("[DEBUG] Listening for clients...\\");
#endif
/* Listen for two clients. */
int num_conn = 0;
while(num_conn < 2)
{
/* Listen for clients. */
listen(lis_sockfd, 253 - player_count);
/* Zero out memory for the client information. */
memset(&cli_addr, 0, sizeof(cli_addr));
clilen = sizeof(cli_addr);
/* Accept the connection from the client. */
cli_sockfd[num_conn] = accept(lis_sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (cli_sockfd[num_conn] < 0)
/* Horrible things have happened. */
error("ERROR accepting a connection from a client.");
#ifdef DEBUG
printf("[DEBUG] Accepted connection from client %d\\", num_conn);
#endif
/* Send the client it's ID. */
write(cli_sockfd[num_conn], &num_conn, sizeof(int));
#ifdef DEBUG
printf("[DEBUG] Sent client %d it's ID.\\", num_conn);
#endif
/* Increment the player count. */
pthread_mutex_lock(&mutexcount);
player_count++;
printf("Number of players is now %d.\\", player_count);
pthread_mutex_unlock(&mutexcount);
if (num_conn == 0) {
/* Send "HLD" to first client to let the user know the server is waiting on a second client. */
write_client_msg(cli_sockfd[0],"HLD");
#ifdef DEBUG
printf("[DEBUG] Told client 0 to hold.\\");
#endif
}
num_conn++;
}
}
/* Gets a move from a client. */
int get_player_move(int cli_sockfd)
{
#ifdef DEBUG
printf("[DEBUG] Getting player move...\\");
#endif
/* Tell player to make a move. */
write_client_msg(cli_sockfd, "TRN");
/* Get players move. */
return recv_int(cli_sockfd);
}
/* Checks that a players move is valid. */
int check_move(char board[][3], int move, int player_id)
{
if ((move == 9) || (board[move/3][move%3] == ' ')) { /* Move is valid. */
#ifdef DEBUG
printf("[DEBUG] Player %d's move was valid.\\", player_id);
#endif
return 1;
}
else { /* Move is invalid. */
#ifdef DEBUG
printf("[DEBUG] Player %d's move was invalid.\\", player_id);
#endif
return 0;
}
}
/* Updates the board with a new move. */
void update_board(char board[][3], int move, int player_id)
{
board[move/3][move%3] = player_id ? 'X' : 'O';
#ifdef DEBUG
printf("[DEBUG] Board updated.\\");
#endif
}
/* Draws the game board to stdout. */
void draw_board(char board[][3])
%c \\", board[0][0], board[0][1], board[0][2]);
printf("-----------\\");
printf(" %c
/* Sends a board update to both clients. */
void send_update(int * cli_sockfd, int move, int player_id)
{
#ifdef DEBUG
printf("[DEBUG] Sending update...\\");
#endif
/* Signal an update */
write_clients_msg(cli_sockfd, "UPD");
/* Send the id of the player that made the move. */
write_clients_int(cli_sockfd, player_id);
/* Send the move. */
write_clients_int(cli_sockfd, move);
#ifdef DEBUG
printf("[DEBUG] Update sent.\\");
#endif