Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

In this assignment you will develop a network application. The server will be a

ID: 3571771 • Letter: I

Question

In this assignment you will develop a network application.

The server will be a concurrent, connection-oriented single-client chat server.

The client will be a chat client to test the server.

A client will send a message to the server, which will then echo the message to the server’s display.

The server will respond to the client with a “RECEIVED” message that includes the number of characters received by the server.

The client will display a message indicating the server received the message and the number of characters the server received in the message.

The client should accept the server’s hostname and optionally, the port number as a commandline argument.

The server should accept an optional port number as a command-line argument.

The client and server should include a default port number if one is not sent as an argument.

The server must be able to gracefully shutdown. If the server receives a CTRL-c to kill it, the server should send a message to all clients indicating it will be shutting down in x seconds, then wait x seconds and gracefully close.

The supported messages of this chat protocol are:

• HELLO – sent by server upon client connection

• BYE – sent by client on disconnect

• NICK – sent by client and contains the user’s selected nickname

• READY – sent by server after successful registration (nickname)

• RETRY – sent by server if nickname selected is not unique

• RECEIVED – sent by the server after receiving a message from the client; will include the number of characters in the message received by the server

The chat protocol specifications are:

• When client connects, the server will send a “HELLO” message to the client.

• When client disconnects from server, client sends a “BYE” message to the server.

• After the client connects, the user will select a nickname, which will be sent to the server using the “NICK” message.

o The server must verify that the nickname selected is unique

If unique, server will send “READY” message to client. The client can now send and receive messages.

If not unique, server will send a “RETRY” message to client and the user will select a different nickname.

• Send a message o User enters a message in the client, which will be sent to the server.

o Server will display the message to the screen and send a “RECEIVED ” message to the client.

Testing

Be sure to properly test all functionality of the client and server. In order to do this, particularly for verifying unique nicknames, it may be necessary to include some code in the client and/or server just for testing purposes. Be sure to clearly mark this code in the comments.

Files to Submit

Submit the following files via turnin:

• All source files

• Makefile

• Readme file

Readme File

The readme file will include the following sections:

• ID block

• File/folder manifest identifying the purpose of each file/folder included in the project

• How to build and run the clients and server

• Test plan – how did you test the clients and server

• Discussion on your development process, including any decisions and/or major problems you encountered and your solution for each

Explanation / Answer

Answer

server_main.c

int g_trace_level = BRIEF_TRACE;

int sockfd;

INT_RET main ()
{
TRACE (BRIEF_TRACE, ("Inside main function "));
struct sockaddr_in serveraddress; /*store serveraddress */
int ret; /*store return value of bind function */
int connfd; /*store return value of accept function */
pthread_t th; /*store thread identification number */
int session_no; /*store session number */
int pthread_ret; /*store return value of pthread_create function */

sockfd = socket (AF_INET, SOCK_STREAM, 0); /*Creating a socket for server for end point communication */
if (-1 == sockfd) /* Error in creating socket */
{
TRACE (DETAILED_TRACE, ("Socket error "));
perror (" Socket Error "); /* printing the error */
exit (ERROR); /* exiting with error */
}

TRACE (DETAILED_TRACE, ("Socket has been created successfully "));
serveraddress.sin_family = AF_INET; /*Address family provides interprocess communication */
serveraddress.sin_port = htons (MY_PORT); /*Port Number of server */
serveraddress.sin_addr.s_addr = htonl (INADDR_ANY); /*Generate the random IP address for bind */

ret = bind (sockfd, (struct sockaddr *) &serveraddress, sizeof (serveraddress)); /*bind a name to a socket */
if (-1 == ret) /* If there is error in binding */
{
TRACE (DETAILED_TRACE, ("Bind Error "));
perror ("BIND"); /* print error */
exit (FAILURE); /* exit with error */
}

TRACE (DETAILED_TRACE, ("Bind successfull "));
listen (sockfd, 5); /*listen for connection on a socket */

TRACE (DETAILED_TRACE, ("Listening... "));
for (session_no = 0; session_no < LIST_SIZE; session_no++) /* loop for all session */
{
conference_list[session_no].head = NULL; /*Set conference list to null */
FD_ZERO (&master[session_no]); /*set master list to zero */
FD_ZERO (&read_fds[session_no]); /*set read_fds list to zero */
fdmax[session_no] = -1;
}

TRACE (DETAILED_TRACE, ("Initializing all lists "));

while (1) /*for communicating to others clients concurrently */
{
printf ("Waiting for client............ ");
connfd = accept (sockfd, (struct sockaddr *) NULL, NULL); /*accept a connection on a socket */

if (-1 == connfd) /* error in accept call */
{
TRACE (DETAILED_TRACE, ("error in accept call "));
if (EINTR == errno) /* if error is of type EINTR */
perror ("Interrupted system call??");
continue;
}

TRACE (DETAILED_TRACE, ("Client has been accepted successfully "));
pthread_ret = pthread_create (&th, NULL, conn_client_entry_handler, (void *) &connfd); /*creating a thread for defferent clients */

TRACE (DETAILED_TRACE, ("Thread is created to handle client "));
if (0 != pthread_ret) /* if there is error in creating thread */
{
TRACE (DETAILED_TRACE,
("Error in creating thred forn handlin client "));
perror ("ERROR:IN CREATING THREAD "); /* print error */
}
}
pthread_exit (NULL);
}

client_main.c

int g_trace_level = DETAILED_TRACE;


INT_RET
main (IN int argc, IN char *argv[])
{
TRACE (BRIEF_TRACE, ("Inside main function "));
char rec_buff[BUFFER_SIZE]; /* stores the data recieved by the client */
char user[INFO_SIZE]; /* stores the name of the user */
int sockfd; /* socket descriptor */
int fdmax, i; /* stores the maximum descriptor */
struct sockaddr_in serveraddress; /* structur of typr sockaddr_in */
fd_set master; /* master list */
fd_set read_fds; /* list of read descriptors */
int ret; /* stores return value */
char send_buf[INFO_SIZE]; /* stores data to be send to other end */

memset (rec_buff, '', BUFFER_SIZE); /* intializing recieve buffer with */
memset (user, '', INFO_SIZE); /* initializing user with */

if (NULL == argv[1]) /* if IP address is not provided of the server is not provided */
{
TRACE (DETAILED_TRACE, ("IP address is not provided "));
printf ("Please provide IP address of the server ");
exit (0); /* exiting */
}

if (NULL == argv[2]) /* if port number at which server is running is not provided */
{
TRACE (DETAILED_TRACE, ("Port number is not provided "));
printf ("Please provide port no of server ");
exit (0); /* exiting */
}

sockfd = socket (AF_INET, SOCK_STREAM, 0); /* socket descriptor is created using socket function */

if (ERR_STATUS == sockfd) /* if error in creating socket */
{
TRACE (DETAILED_TRACE, ("Error in creating socket "));
perror ("Socket Error");
exit (ERROR); /* exit with error */
}
TRACE (DETAILED_TRACE, ("Socket has been created successfully "));

serveraddress.sin_family = AF_INET; /* specifying the family as IPv4 */
serveraddress.sin_port = htons (atoi (argv[2])); /* setting the port field of structure */
serveraddress.sin_addr.s_addr = inet_addr (argv[1]); /* setting the address field of structure */

ret = connect (sockfd, (struct sockaddr *) &serveraddress, /* connecting to the server */
sizeof (serveraddress));

if (ERR_STATUS == ret) /* error in connecting to server */
{
TRACE (DETAILED_TRACE, ("Error in connecting to socket "));
perror ("Connect Error");
exit (ERROR); /* exiting with error */
}

TRACE (DETAILED_TRACE, ("Connection is successfully done "));
FD_ZERO (&master); /* initializing the master list with 0 */
FD_ZERO (&read_fds); /* initializing the read_fd list with 0 */
FD_SET (0, &master); /* setting the master list with descriptor of stdin */
FD_SET (sockfd, &master); /* setting the master list with socket descriptor */
fdmax = sockfd; /* setting the fdmax with the descriptor value of sockfd */

TRACE (DETAILED_TRACE,
("Calling client_registration_And_Authentication function "));
conn_client_registration_and_authentication (sockfd, user, rec_buff); /* calling function to register or authenticate client */
printf ("%s ", rec_buff); /* printing data recieved by client */

if (strcmp (rec_buff, "INVALID") == 0) /* if client is invalid */
{
TRACE (DETAILED_TRACE, ("Invalid username and password "));
printf ("Invalid Username and Password ");
exit (0); /* exit from system */
}

if (strcmp (user, "ADMIN") == 0) /* if client is identified as administrator */
{
TRACE (DETAILED_TRACE, ("User is identified as administrator "));
printf ("Welcome administrator...... ");
TRACE (DETAILED_TRACE, ("Calling admin_operation function "));
conn_admin_operation (sockfd); /* calling function to handle administartor */
}

else /* if client is not an administartor */
{
TRACE (DETAILED_TRACE, ("%s is validated", user));
memset (send_buf, '', INFO_SIZE); /* initializing send buffer with */
TRACE (DETAILED_TRACE, ("Calling choice_for_conference function "));
conn_choice_for_conference (sockfd); /* calling the function to as for choice of conference */
// user[strlen (user) - 1] = '';   
sleep (1); /* for synchronization */
strcpy (send_buf, user); /* copying user name into buffer */
strcat (send_buf, " has joined conversation ");
wrap_write_to_socket (sockfd, send_buf); /* writing to socket about joining of conversation */
while (' ' != getchar ()); /* claering the input buffer */

TRACE (DETAILED_TRACE, ("Entering while loop "));
while (1)
{
read_fds = master; /* setting read_fds with master list */
TRACE (DETAILED_TRACE, ("Waiting for select command to unblock "));
select (fdmax + 1, &read_fds, NULL, NULL, NULL); /* select command */
TRACE (DETAILED_TRACE, ("Outside select command "));
for (i = 0; i <= fdmax; i++) /* when there is some data to read or write by client */
{
if (FD_ISSET (i, &read_fds)) /* identifying which descriptor is set */
{
TRACE (DETAILED_TRACE,
("calling communicate_with_other_clients function "));
conf_communicate_with_other_clients (i, sockfd, user); /* calling function to raed or wrote data to other clients */
}
}
}
}
return 0;
}