In: Computer Science
Complete the code. You are given a zip file that contains an online multiplayer Tic-tac-toe system. The system comprises two main modules: Server and Client and uses server – client communication between them. You will have to extend the client and server files to include the missing communications using socket programming. In this game, the server runs indefinitely, waiting for a client. A client connects to the server to see if there are other players online. A client then invites one of the players to play the game. If the asked player accepts the invitation, the game will start. At the end of the game, the two players can either play again or quit the game and return to the server command line. The Tic-tac-toe Client: In the beginning, the client will prompt the player to specify the server IP address. The client will then list all the commands supported by the client. There are four commands included in the client implementation: join, list, invite and leave. The client creates two different threads to handle the connection with the server and the opponent client. Client commands: join: followed by a username that the player wishes to use in the game. list: list the usernames of all online players. invite: send a play request to another player. leave: leave the game; this will remove the player name from the online player list. The Tic-tac-toe Server: The server maintains clients' information in a hash-map data structure where the client IP address and username are used as a key; this allows multiple clients with a different IP address to use the same username. The server uses a multi-threaded approach to concurrent server design: for each client, a new thread is created to handle the client request. This thread will exit when the client sends a leave command to the server.
Fill in the coed that is numbered
SERVER.C
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "uthash.h"/*Create and maintain HashMap functions*/
#define QLEN 15 /* max number of pending incoming connections
*/
#define BUFFERSIZE 1500 /* max size of buffer*/
#define STRLEN 100 /* max string length */
typedef struct {
char name [STRLEN];
char ip_addr [STRLEN];
} record_key_t;
typedef struct {
record_key_t key;
int status;
UT_hash_handle hh;
} record_t;
/* functions prototype*/
void * server_thd(void * parm); /* a function to handle communication with clients */
void get_online_Players(const void *key, const void *value, void *obj); /* a function to handle the li$
int add_user(char name [STRLEN], char ip_addr [STRLEN]);
void print_users();
void user_left(char name [STRLEN], char ip_addr [STRLEN]);
void user_join(record_t *p);
record_t *users = NULL; /* init. hashmap list*/
pthread_mutex_t mut; /* Mutex to prevent multiple write. */
int size = 0;
int main () /* the main function*/
{
struct sockaddr_in sarver_ad; /* to store server local ip and port */
struct sockaddr_in client_ad; /* to store client ip and port */
int server_fd, client_fd; /* socket descriptors */
int port = 9090; /* protocol port number */
int addr_len; /* length of address */
pthread_t thrd_id; /* variable to hold thread ID */
pthread_mutex_init(&mut, NULL);
bzero( &sarver_ad, sizeof(sarver_ad)); /* clear sockaddr struct.*/
/* 1) here you need to set up the sockaddr_in*/
/* set address family */
/* set the local IP address to any local address */
/* set the local port to 9090 */
/* Create a socket */
/* 2) here you need to create a socket*/
/* 3) here you need to create a socket Bind a local address to the socket */
/* 4) here you need to make the server listen on server_fd for incoming connections */
/* Main server loop - accept and handle requests */
fprintf(stderr, "Server up and running.\n");
while (1) {
/* 5) here you need to make accept incoming connections before the new thread is created*/
/* Create seperate thread for each client */
pthread_create(&thrd_id, NULL, server_thd, (void *) client_fd );
}
close(server_fd); /* Close socket */
}
int add_user(char name [STRLEN], char ip_addr [STRLEN])
CLIENT.C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdbool.h>
#include <pthread.h>
#define MAXBUFFER 100 /*Maximum buffer size*/
#define MAXSTRINGLEN 100 /*Maximum String length*/
#define SERVERPORTNUM 9090 /*server port number*/
#define HOSTPORTNUM 12345 /* Local port number */
#define PEERPORTNUM 12345 /* peer port number */
char name[MAXSTRINGLEN], /* name used to join the server
*/
peer_name[MAXSTRINGLEN];/* name of opponent */
pthread_t thrid_id; /*thread Id*/
int current_player=0; /* local user score*/
int other_player=0; /* remote user score*/
void tic_tac_toe(int socket, char * buffer, int playerID); /*the
tic tac toe game.*/
void * serverConn(void * parm); /* Thread function to handle
communication with the server */
void * peerConn(char * ip); /* Thread function used when we want to
open a connection with$
void print_instraction(); /* to print the game instructions */
int server_socket, peer_socket, listn_socket, consocket; /* All
socket descriptors are stored as globa$
int ingame, turn; /* Some variables to handle the flow of the game.
*/
int main(int argc, char *argv[])
{
printf("Enter Server's IP: ");
const char server[30]; /* store IP address of server */
scanf("%s",server);
/* Establish connection with the server */
struct sockaddr_in dest;
/* 1) here you need to create a socket named
'server_socket' to connect to the server */
memset(&dest, 0, sizeof(dest));
/* 2) here you need to creat sockaddr_in to store server
info.*/
/*connect to the server*/
/* 3) here you need to 'server_socket' to the
server.*/
pthread_create(&thrid_id, NULL, serverConn, (void*) &server_socket);
/* For Invitation */
/* Bind to a socket and start listening for incomming connections.
peer-to-peer*/
struct sockaddr_in peer;
struct sockaddr_in serv;
socklen_t socksize = sizeof(struct sockaddr_in);
memset(&serv, 0, sizeof(serv));
/* 4) here you need to set up the sockaddr_in*/
/* 5) here you need to create a socket*/
/* 6) here you need to create a socket Bind a local address to the
socket */
/* 7) here you need to make the server listen on server_fd for
incoming connections, Only accept o$
/* 8) here you need to make accept incoming connections before the
new thread is created*/
char buffer[MAXBUFFER]; /* Buffer to hold data exchanged
*/
int len;
/* handle peer connection request */
while(consocket)
{
pthread_cancel(thrid_id);
/* Receive peer's name and store it as current opponent */
len = recv(consocket, buffer, MAXBUFFER, 0);
buffer[len] = '\0';
strcpy(&peer_name, buffer);
printf("\n%s has challenged you. Accept challenge? (y/n) ",
peer_name);
/* Ask for approval */
fgets(buffer, sizeof(buffer), stdin);
buffer[strlen(buffer)-1] = '\0';
if (strcmp(buffer, "y") == 0)
{
current_player=0;
other_player=0;
printf("\nYour Score: %d", current_player);
printf("\nOpponent's Score: %d",other_player);
ingame = 1;
send(consocket, buffer, strlen(buffer), 0);
}
else
{
current_player=0;
other_player=0;
send(consocket, buffer, strlen(buffer), 0);
printf("\nYou declined...\n");
ingame = 0;
}
/* Play game until one of the player declines. */
turn = 0;
int playerID = 2;
/* Close all sockets before the program exits */
close(listn_socket);
close(consocket);
close(peer_socket);
close(server_socket);
return EXIT_SUCCESS;
}
Solution: Add following lines in the mentioned position. I have solved few parts, kindly try to solve remaining on your own.
In SERVER.C
sarver_ad.sin_family = AF_INET;
sarver_ad.sin_addr.s_addr = INADDR_ANY;
sarver_ad.sin_port = htons(port);
(2.) here you need to create a socket
if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
error("Error thrown by Socket");
}
(3.) here you need to create a socket Bind a local address to the socket
if(bind(server_fd, (struct sockaddr *) &sarver_ad, sizeof(sarver_ad)) == -1) {
error("Error thrown by Bind");
}
(4.) here you need to make the server listen on server_fd for incoming connections
if(listen(server_fd, 10) < 0){
error("Error thrown by Listen");
}
(5.) here you need to make accept incoming connections before the new thread is created
socklen_t client_len = sizeof(client_ad);
client_fd = accept(server_fd, (struct sockaddr *) &client_ad, &client_len);
if(client_fd < 0){
error("Error thrown by Accept");
}
In CLIENT.C
(1.) here you need to create a socket named 'server_socket' to connect to the server
if((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0){
error("Error thrown by Socket");
}
(2.) here you need to creat sockaddr_in to store server info.*/
struct hostent *server_entry; // Fetches ipv4 address
server_entry = gethostbyname(server);
dest.sin_family = AF_INET;
bcopy((char*) server_entry->h_addr, (char *) &dest.sin_addr.s_addr, server_entry->h_length);
dest.sin_port = htons(SERVERPORTNUM);
(3.) here you need to connect 'server_socket' to the server.
if(connect(server_socket, (struct sockaddr *) &dest, sizeof(dest)) < 0){
error("Error thrown by Connect");
}
Similarly solve the remaining parts.
Let me know if you face doubt with any part.