TCP socket programming:

Write a server program and client program. The server is launched in a terminal; the client is launched in two different terminals (two instances of the client program in two separate terminals). This results in three terminals: one server terminal and two client terminals. The clients accept a keyboard input from the user. When the user presses ENTER/RETURN key, the client transmits the input sentence to the server and get back in the keyboard input mode. The server displays the transmitted sentences on its terminal as they arrives.

Submit a report comprising:

(0) Introduction of your program (10-point);

(1) Full source code (30-point);

(2) Screen shots of the entire execution sequence (30-point);

(3) Screen shots of Wireshocks showing the details of the packets exchanged (30-point).

 

Solution:

Part A

  1. Introduction

 

This is a pair of programs that allows a server to communicate with its multiple clients, and each client to communicate with the server but not each other. The programs communicate through a TCP connection, and are run on Ubuntu. These programs use socket programming, specifically the Berkley Socket programming, to model a many-to-one relationship.

 

The server program is started by navigating to its parent directory via the terminal. The command ./server.out is used to execute the program. It will display a message that the program has started and is listening for incoming connections. To start the client program, in a separate terminal window, the user must navigate to the parent directory of the client program; after which the client program can be executed via the command ./client.out followed by the IP address of the server for example ./client.out 127.0.0.1 .

 

When a client connects a message will be displayed in the server’s terminal window stating that a client has been connected and a child process has been created to handle the client’s request. The user can now enter text via the keyboard in the client program’s terminal window. After a message is sent to the server it is displayed in the format “Client Says:<message_from_client>. The Client now has the opportunity to send as many messages to the client.

 

 

  1. Source code – Client Program

 

#include <stdlib.h>

 

#include <stdio.h>

 

#include <sys/types.h>

 

#include <sys/socket.h>

 

#include <netinet/in.h>

 

#include <string.h>

 

#include <arpa/inet.h>

 

 

 

#define MAXLINE 1000 /*max text line length*/

 

#define SERV_PORT 4000 /*port*/

 

 

 

int

 

main(int argc, char **argv)

 

{

 

int sockfd;

 

struct sockaddr_in servaddr;

 

char sendline[MAXLINE], recvline[MAXLINE];

 

 

 

//basic check of the arguments

 

//additional checks can be inserted

 

if (argc !=2) {

 

perror(“Usage: TCPClient <IP address of the server”);

 

exit(1);

 

}

 

 

 

//Socket will be created for client

 

 

if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) <0) {

 

perror(“Problem in creating the socket”);

 

exit(2);

 

}

 

 

 

//Creation of the socket

 

memset(&servaddr, 0, sizeof(servaddr));

 

servaddr.sin_family = AF_INET;

 

servaddr.sin_addr.s_addr= inet_addr(argv[1]);

 

servaddr.sin_port =  htons(SERV_PORT); //convert to big-endian order

 

 

 

//Client connected to socket

 

if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr))<0) {

 

perror(“there was an error while connecting to the server”);

 

exit(3);

 

}

 

 

 

while (fgets(sendline, MAXLINE, stdin) != NULL) {

 

 

 

send(sockfd, sendline, strlen(sendline), 0);

 

 

 

if (recv(sockfd, recvline, MAXLINE,0) == 0){

 

//error: server terminated prematurely

 

perror(“The server terminated prematurely”);

 

exit(4);

 

}

 

}

 

 

 

exit(0);

 

}

 

 

 

 

Server Program

 

#include <stdlib.h>

 

#include <stdio.h>

 

#include <sys/types.h>

 

#include <sys/socket.h>

 

#include <netinet/in.h>

 

#include <string.h>

 

#include <unistd.h>

 

 

 

#define MAXLINE 1000 /*max text line length*/

 

#define SERV_PORT 4000 /*port*/

 

#define LISTENQ 5 /*maximum number of client connections*/

 

 

 

int main (int argc, char **argv)

 

{

 

int listenfd, connfd, n;

 

pid_t childpid;

 

socklen_t clilen;

 

char buf[MAXLINE];

 

struct sockaddr_in cliaddr, servaddr;

 

 

 

//Create a socket for the client

 

 

 

if ((listenfd = socket (AF_INET, SOCK_STREAM, 0)) <0) {

 

perror(“Problem in creating the socket”);

 

exit(2);

 

}

 

 

 

 

 

//prepare the socket address

 

servaddr.sin_family = AF_INET;

 

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

 

servaddr.sin_port = htons(SERV_PORT);

 

 

 

//bind the socket

 

bind (listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));

 

 

 

//listen to the socket and then listen for clients

 

listen (listenfd, LISTENQ);

 

 

 

printf(“%s\n”,”Server Started! | listening for connections…”);

 

 

 

for ( ; ; ) {

 

 

 

clilen = sizeof(cliaddr);

 

//accept connection

 

connfd = accept (listenfd, (struct sockaddr *) &cliaddr, &clilen);

 

 

 

printf(“%s\n”,”Client connected!”);

 

 

 

if ( (childpid = fork ()) == 0 ) {

 

 

 

printf (“%s\n”,”Child process created”);

 

 

 

//close listening socket

 

close (listenfd);

 

 

 

while ( (n = recv(connfd, buf, MAXLINE,0)) > 0)  {

 

printf(“%s”,”Client Says:”); //Print to the screen what the client says

 

puts(buf);

 

send(connfd, buf, n, 0);

 

}

 

 

 

if (n < 0)

 

printf(“%s\n”, “Read error”);

 

exit(0);

 

}

 

//close socket of the server

 

close(connfd);

 

}

 

}