You are on page 1of 20

A Project Report

on

Chat application using UDP socket programming.


carried out as a part of Computer Networks(CS1602)
Submitted by

Avneesh Nolkha (169104026)


Stuti Pandey(169104113)
Tamanna Sandhir(169104121)
Tanmay Gautam (169104122)

6th Semester, B.tech, CCE

in partial fulfilment for the award of the degree

of

BACHELOR OF TECHNOLOGY
In

Computer & Communication Engineering

Department of Computer & Communication Engineering,


School of Computing and IT,
Manipal University Jaipur,
April, 2019
Page 1 of 20
DECLARATION

I hereby declare that the project entitled “Chat application using UDP socket programming”

submitted as part of the partial course requirements for the course Computer Networks, for the award

of the degree of Bachelor of Technology in Computer & Communication Engineering at Manipal

University Jaipur during the 6th Semester, April, 2019 , has been carried out by me. I declare that the

project has not formed the basis for the award of any degree, associate ship, fellowship or any other

similar titles elsewhere.

Further, I declare that I will not share, re-submit or publish the code, idea, framework and/or

any publication that may arise out of this work for academic or profit purposes without obtaining the

prior written consent of the Course Faculty Mentor and Course Instructor.

Signature of the Student:

Place:

Date:

Page 2 of 20
ACKNOWLEDGEMENT

If words are considered as a symbol of approval and token of appreciation then let the words
play the heralding role expressing my gratitude. The satisfaction that accompanies that the
successful completion of any task would be incomplete without the mention of people whose
ceaseless cooperation made it possible, whose constant guidance and encouragement crown all
efforts with success. We are grateful to our project guide Dr. Anshuman Kalla for the guidance,
inspiration and constructive suggestions that helpful us in the preparation of this project. We also
thank our colleagues who have helped in successful completion of the project.

Page 3 of 20
Table of Contents

Heading Page No.


1. Cover Page 1

2. Declaration 2

3. Acknowledgement 3

4. Introduction 4

5. Software Architecture 6

6. Contribution 8

7. System Specification 9

8. Work Done 10

Page 4 of 20
Introduction

Teleconferencing or Chatting, is a method of using technology to bring people and ideas


“together” despite of the geographical barriers. The technology has been available for years but
the acceptance it was quite recent. Our project is an example of a chat server. It is made up of
two applications the client application, which runs on the user’s PC and server application, which
runs on any PC on the network. To start chatting client should get connected to server where they
can practice two kinds of chatting, public one (message is broadcasted to all connected users)
and private one (between any 2 users only) and during the last one security measures one taken.

Page 5 of 20
Software Architecture

Socket Overview

A socket is an object that represents a low level access point to the IP stack. This socket can be
opened or closed or one of a set number of intermediate states. A socket can send and receive
data down disconnection. Data is generally sent in blocks of few kilobytes at a time for
efficiency; each of these block are called a packet. All packets that travel on the internet must use
the Internet Protocol. This means that the source IP address, destination address must be included
in the packet. Most packets also contain a port number. A port is simply a number between 1 and
65,535 that is used to differentiate higher protocols. Ports are important when it comes to
programming your own network applications because no two applications can use the same port.
Packets that contain port numbers come in two flavors: UDP and TCP/IP. UDP has lower latency
than TCP/IP, especially on startup. Where data integrity is not of the utmost concerned, UDP can
prove easier to use than TCP, but it should never be used where data integrity is more important
than performance; however, data sent by UDP can sometimes arrive in the wrong order and be
effectively useless to the receiver. TCP/IP is more complex than UDP and has generally longer
latencies, but it does guarantee that data does not become corrupted when travelling over the
internet. TCP is ideal for file transfer, where a corrupt file is more unacceptable than a slow
download; however, it is unsuited to internet radio, where the odd sound out of place is more
acceptable than long gaps of silence.

UDP Ports

The User Datagram Protocol is an unreliable, connectionless oriented protocol that uses an IP
address for the destination host and a port number to identify the destination application.

The UDP port number is distinct from any physical port on a computer such as a COM port or an
I/O port address. The UDP port is a 16-bit address that exists only for the purpose of passing
certain types of datagram information to the correct location above the transport layer of the
protocol stack.

Page 6 of 20
A UDP datagram header consists of four (4) fields of two bytes each:

1. source port number

2. destination port number

3. datagram size

4. checksum

Using UDP Sockets

End point is a combination of IP address and port number. Endpoint objects allow you to easily
establish and communicate over TCP/IP network connections between client and server
processes, possibly residing on different hosts. The Endpoint class follows a telephone-like
model of networking: clients "call" servers and servers "answer" clients. Once a network
connection is established between a client and a server, the two can "talk" to each other by
reading from and writing to the connection.

Software Process Model

The Software Process Model used is the Spiral Model. The choice for this model is in the light of
the enhancements that we foresee for the future. The enhancements would be in the area of
Networks being introduced into the software.

Conclusion

This chapter has given a broad picture of the design of the software in terms of the different
modules used. It also gives us an idea about the degree to which each module performs related
tasks. We also get an idea about the interdependence among the modules.

Page 7 of 20
Contribution to the Project

A project is successfully completed only when there is contribution of all the members of a team.
Each member in the project has a required objective to accomplish .In same way to complete this
project we divided our work in equal manner. Instead of selecting a particular task to do
individually, we divided a single task in multiple subtasks so that we all can work together on the
same phase or task of the project. Doing so no team member had to wait to show his or her
capabilities.

Page 8 of 20
SYSTEM SPECIFICATION

Hardware requirements
In hardware requirement we require all those components which will provide us the platform for the
development of the project. The minimum hardware required for the development of this project is as
follows— Ram- minimum 128 MB Hard disk—minimum 5 GB Processor- Pentium 3 Floppy drive 1.44”
inch CD drive These all are the minimum hardware requirement required for our project. We want to
make our project to be used in any. Type of computer therefore we have taken minimum configuration
to a large extent.128 MB ram is used so that we can execute our project in a least possible RAM.5 GB
hard disk is used because project takes less space to be executed or stored. Therefore minimum hard
disk is used. Others enhancements are according to the needs. 3.2 Software requirements Software’s
can be defined as programs which run on our computer .it act as petrol in the vehicle. It provides the
relationship between the human and a computer. It is very important to run software to function the
computer. Various software’s are needed in this project for its development. Which are as follows—?
Operating system—Windows 7 Others—Visual Studio We will be using visual basic as our front hand
because it is easier to use and provides features to the users which is used for the development of the
project.

Page 9 of 20
Source Code

Server Code
/* server */

#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>

#include "chat.h"

typedef struct client {


struct sockaddr_in address; //will hold the client's address information
char username[USERNAME_LEN]; //will hold the clients username and will be
initialized when each client starts and sends it's username and a special code informative of
joining server
struct client *next;
} client;

int sockfd;

client clientList;
char requestBuffer[BUF_SIZE];
char responseBuffer[BUF_SIZE + USERNAME_LEN];

char sender_name[USERNAME_LEN];

char *colors[NCOLORS] = { RED, GREEN, YELLOW, BLUE, MAGENTA,


CYAN, LRED, LGREEN, LYELLOW, LBLUE, LMAGENTA,
LCYAN
};

void userColor(int n) {
strcat(responseBuffer, colors[(n % NCOLORS)]);
}

/* function returns true if the two passes internet address are identical */

Page 10 of 20
int clientCompare(struct sockaddr_in client1, struct sockaddr_in client2) {
if(strncmp
((char *) &client1.sin_addr.s_addr, (char *) &client2.sin_addr.s_addr,
sizeof(unsigned long)) == 0) {
if(strncmp((char *) &client1.sin_port, (char *) &client2.sin_port, sizeof(unsigned short))
== 0) {
if(strncmp
((char *) &client1.sin_family, (char *) &client2.sin_family,
sizeof(unsigned short)) == 0) {

return TRUE;
}
}
}
return FALSE;
}

/* sends message to all clients except for the sender */


/* will send to all clients if second argument `global` is set to TRUE */
void broadcast(struct sockaddr_in sender, int global) {
client *cli = clientList.next; //client list iterator

while(cli != NULL) {
//if sender isn't the client send out the message // may need separate clientCompare function
// use username for comparisons so noone can connect with the same username
if(clientCompare(sender, cli->address) == FALSE || global) {
printf("Sending message to %s\n", cli->username);
if((sendto
(sockfd, responseBuffer, strlen(responseBuffer), 0,
(struct sockaddr *) &cli->address, sizeof(struct sockaddr))) == SYSERR) {

perror("sendto");
close(sockfd);
exit(EXIT_FAILURE);
}
}

cli = cli->next;
}
}

int isConnected(struct sockaddr_in newClient) {


client *element = &clientList;

while(element != NULL) {
if(clientCompare(element->address, newClient)) {

Page 11 of 20
strncpy(sender_name, element->username, USERNAME_LEN);
printf("Client is already connected\n");
return TRUE;
}
element = element->next;
}
printf("Client is not already connected\n");
return FALSE;
}

/* Used to add new clients dynamically to our server's client linked list */
/* connects a client to the server */
int connectClient(struct sockaddr_in newClient, char *username) {
printf("Attempting to connect client: %s\n", username);
client *element = &clientList;

while(element != NULL) {
if(strcmp(element->username, username) == 0) {
printf("Cannot connect client user already exists\n");
strcpy(responseBuffer, "");
strcat(responseBuffer, ERROR);
if((sendto
(sockfd, responseBuffer, strlen(responseBuffer), 0, (struct sockaddr *) &newClient,
sizeof(struct sockaddr))) == SYSERR) {
perror("sendto");
close(sockfd);
exit(EXIT_FAILURE);
}
return SYSERR;
}
element = element->next;
}

element = &clientList;
while(element->next != NULL) {
element = element->next;
}
element->next = malloc(sizeof(client));
element = element->next;

element->address = newClient;
strncpy(element->username, username, USERNAME_LEN);
element->next = NULL;
printf("Client connected\n");
return OK;
}

Page 12 of 20
/* Used to remove clients dynamically from our server's client linked list */
/* disconnects a client from the server */
int disconnectClient(struct sockaddr_in oldClient) {
printf("Attempting to disconnect client\n");
client *temp;
client *element = &clientList;

while(element->next != NULL) {
if(clientCompare(oldClient, element->next->address)) {
temp = element->next->next;
free(element->next);
element->next = temp;
printf("Client disconnected\n");
return OK;
}
element = element->next;
}

printf("Client was not disconnected properly\n");


return SYSERR;
}

/* Prints out the server's client list for debugging */


void printClientList() {
client *cli = clientList.next;
int count = 1;

while(cli != NULL) {
printf("Client %d\n", count);
printf("%s\n", cli->username);
printf("ip: %s\n", inet_ntoa(cli->address.sin_addr));
printf("port: %d\n\n", ntohs(cli->address.sin_port));
cli = cli->next;
count++;
}
}

void sendClientList(struct sockaddr_in sender) {


client *cli = clientList.next;

while(cli != NULL) {
if(clientCompare(sender, cli->address) == FALSE) {
strcpy(responseBuffer, "");
userColor(cli->address.sin_port);
strcat(responseBuffer, cli->username);

Page 13 of 20
strcat(responseBuffer, RESET "\n");
if((sendto
(sockfd, responseBuffer, strlen(responseBuffer), 0, (struct sockaddr *) &sender,
sizeof(struct sockaddr))) == SYSERR) {

perror("sendto");
close(sockfd);
exit(EXIT_FAILURE);
}
}
cli = cli->next;
}
}

/* Main Server Process */


int main(int argc, char *argv[]) {

int server_port, nbytes;


int address_size = sizeof(struct sockaddr_in);
struct sockaddr_in server_addr;
struct sockaddr_in sender_addr; //sockaddr internet structs to handle address family,port
number, and internet address

//note sockaddr_in is the same size as sockaddr and can be cast to (struct sockaddr *)

bzero(requestBuffer, BUF_SIZE);
bzero(responseBuffer, BUF_SIZE + USERNAME_LEN); //zero out buffers

if(argc != 2) {
fprintf(stderr, "Usage: %s portnum\n", argv[0]);
exit(EXIT_FAILURE);
}

server_port = atoi(argv[1]); //server_port now holds the user inputed port number

//SOCK_DGRAM are datagram or connectionless sockets they use UDP and will not
nessecarily arrive in order or arrive at all
sockfd = socket(AF_INET, SOCK_DGRAM, 0); //returns socket file descriptor that can use
send() and recv() for data transmission
// last argumant protocol number given 0 will derive to protocol based on the 2nd argument
type passed

if(sockfd == SYSERR) { //socket() returns -1 on error


close(sockfd);
fprintf(stderr, "Failed to get socket file descriptor\n");
exit(EXIT_FAILURE);

Page 14 of 20
}

server_addr.sin_family = AF_INET; //address family we should use for this assignment


server_addr.sin_port = htons(server_port); //flips port argument to big endian and assigns to
our port
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //binds socket to all the computers
interfaces
//INADDR_ANY is defined as 0 but is flipped to network long for consistency

memset(&(server_addr.sin_zero), '\0', 8); //sets rest of sockaddr_in to 0's 8 bytes worth

if(bind(sockfd, (struct sockaddr *) &server_addr, sizeof(struct sockaddr)) == SYSERR) {


close(sockfd);
fprintf(stderr, "Failed to bind on socket!\n");
exit(EXIT_FAILURE);
}

while(1) { // main server receive/response loop


bzero(responseBuffer, BUF_SIZE + USERNAME_LEN); //zero out buffer //we might be
able to remove this to improve performance

/*
* LISTEN FOR PACKETS
*/
if((nbytes =
recvfrom(sockfd, requestBuffer, BUF_SIZE - 1, 0, (struct sockaddr *) &sender_addr,
(unsigned int *) &address_size)) == SYSERR) {
perror("recvfrom");
close(sockfd);
exit(EXIT_FAILURE);
}

requestBuffer[nbytes] = '\0'; // ensures that recieved message is null terminated


printf("Received packet of %d bytes\n~\n%s\n~\n\n", nbytes, requestBuffer);

if(isConnected(sender_addr)) {
userColor(sender_addr.sin_port);
strcat(responseBuffer, sender_name);
if(strcmp(CLOSE, requestBuffer) == 0) {
if(disconnectClient(sender_addr) == OK) { //upon success of disconnect broadcast
message to clients that user left

strcat(responseBuffer, RED " disconnected" RESET "\n");

broadcast(sender_addr, TRUE); //when sender is NULL it will broadcast to


everyone in the client list

Page 15 of 20
}
printClientList();
}
else if(strcmp(EXIT, requestBuffer) == 0) {
strcat(responseBuffer, RED " shutdown the server" RESET "\n");
broadcast(sender_addr, TRUE);
printf("Exiting Server\n");
close(sockfd);
exit(OK);
}
else if(strcmp(LIST, requestBuffer) == 0) {
sendClientList(sender_addr);
}
else {
strcat(responseBuffer, RESET);
strcat(responseBuffer, USERNAMExMESSAGE); //inserts string between
username and message to look nice
strcat(responseBuffer, requestBuffer);

printf("Message:\n[%s]\n", responseBuffer);
//go through entire linked list and echo back the message to all clients connected with
proper username of the sender
broadcast(sender_addr, FALSE); //sends message to all except sender
}
}
else {

if(connectClient(sender_addr, requestBuffer) == OK) {


userColor(sender_addr.sin_port);
strcat(responseBuffer, requestBuffer);
strcat(responseBuffer, GREEN " connected" RESET "\n");
broadcast(sender_addr, TRUE);
sendClientList(sender_addr);
}
printClientList();
}

close(sockfd);
return OK;
}

Page 16 of 20
Client Code

/* client */

#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <pthread.h>
#include "chat.h"

int done = FALSE; //boolean that tells threads when client program is finished

int sockfd; //socket file descriptor for client

pthread_mutex_t mutexsum = PTHREAD_MUTEX_INITIALIZER; //mutual exclusion for our


threads

void *sender(); // thread function that will take user input and send out messages to
server

void *receiver(); // thread function that will listen for received messages coming from
the server

char sendBuffer[BUF_SIZE];
char receiveBuffer[BUF_SIZE + USERNAME_LEN + 2];

int main(int argc, char *argv[]) {


bzero(sendBuffer, BUF_SIZE); //zero out both buffers
bzero(receiveBuffer, BUF_SIZE + USERNAME_LEN + 2);

int portnum;
char username[USERNAME_LEN];

if(argc != 4) {
fprintf(stderr, "Usage: %s [server] [portnum] [username]\n", argv[0]);
exit(EXIT_FAILURE);
}

Page 17 of 20
portnum = atoi(argv[2]);
strncpy(username, argv[3], USERNAME_LEN);

printf("server: %s\n", argv[1]);


printf("port: %d\n", portnum);
printf("username: %s\n", username);

//allow server to resolve hostnames or use ip's


struct hostent *server_host;

if((server_host = gethostbyname(argv[1])) == NULL) { // get the host info


fprintf(stderr, "Failed to resolve server host information\n");
exit(EXIT_FAILURE);
}

printf("Host: %s\n", server_host->h_name);


printf("IP Address of host: %s\n", inet_ntoa((struct in_addr)
*((struct in_addr *)
server_host->h_addr)));

struct sockaddr_in server_addr; // server's internet address used for all sends and receives

sockfd = socket(AF_INET, SOCK_DGRAM, 0);


if(sockfd == -1) { //socket() returns -1 on error
close(sockfd);
fprintf(stderr, "Failed to get socket file descriptor\n");
exit(EXIT_FAILURE);
}

server_addr.sin_family = AF_INET; // host byte order


server_addr.sin_port = htons(portnum); // short, network byte order
server_addr.sin_addr = *((struct in_addr *) server_host->h_addr);
memset(&(server_addr.sin_zero), '\0', 8); // zero the rest of the struct

//Make connection to server socket so we can use send() and recv() to read and write the
server
if(connect(sockfd, (struct sockaddr *) &server_addr, sizeof(struct sockaddr)) == SYSERR) {
close(sockfd);
fprintf(stderr, "Failed to connect to remote server!\n");
exit(EXIT_FAILURE);
}

// Create and send out open message to the server so it knows our username and we are
identified as a connected client
strcpy(sendBuffer, username);

Page 18 of 20
if(send(sockfd, sendBuffer, strlen(sendBuffer), 0) == SYSERR) {
perror("send");
close(sockfd);
exit(EXIT_FAILURE);
}

//create threads
//Thread 1: takes in user input and sends out messages
//Thread 2: listens for messages that are comming in from the server and prints them to screen
// Set up threads
pthread_t threads[2];
pthread_attr_t attr;

pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

// Run the sender and receiver threads


pthread_create(&threads[0], &attr, sender, NULL);
pthread_create(&threads[1], &attr, receiver, NULL);

// Wait until done is TRUE then exit program


while(!done);

close(sockfd);
return OK;
}

void *sender() {
while(1) {
bzero(sendBuffer, BUF_SIZE);
fgets(sendBuffer, BUF_SIZE, stdin);

//send message to server


if(send(sockfd, sendBuffer, strlen(sendBuffer), 0) == SYSERR) {
perror("send");
done = TRUE;
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);
}

// Check for quiting


if(strcmp(sendBuffer, CLOSE) == 0 || strcmp(sendBuffer, EXIT) == 0) {
done = TRUE;
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);
}

Page 19 of 20
pthread_mutex_unlock(&mutexsum);
}
}

void *receiver() {
int nbytes;

while(1) {
bzero(receiveBuffer, BUF_SIZE);

//Receive messages from server


if((nbytes = recv(sockfd, receiveBuffer, BUF_SIZE - 1, 0)) == SYSERR) {
perror("recv");
done = TRUE;
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);
}

receiveBuffer[nbytes] = '\0';
if(strcmp(ERROR, receiveBuffer) == 0) {
printf("Error: The username %s is already taken.\n", sendBuffer);
done = TRUE;
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);
}
else {
printf("%s", receiveBuffer);
pthread_mutex_unlock(&mutexsum);
}
}
}

Page 20 of 20

You might also like