Skip to content

kattungakrish/Unix-Socket-Programming

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Term Project: EE 450- Introduction to Computer Networks.
University of Southern California, Los Angeles, CA
--------------------------------------------------------------------------------
Full Name: Krishi Satya Sai Kattunga
--------------------------------------------------------------------------------
*MY WORK:

This project uses unix socket programming to implement a client-server
model system, with 3 servers (A main server, 2 backend servers A and B) and
2 and possibly more clients. This client-server model is capable of supporting
the implementation of a  simple application where, 1 or more clients ask the main server
for recommending possible friends of a user (denoted by their user ID) in a
particular country. The main server itself doesn't have this information stored directly
but instead, it knows which backend server to contact for it does so.
If the respective backend server has the required information, they reply with
their recommendations to the main server which then passes on this information
as its recommendations to the client for all possible friends of the queried user
ID in that particular country.

The clients communicate with the main server using TCP thus maintaining a TCP
connection for the whole duration of their communication, whereas the communications
between the main server and either of the backend servers is implemented using UDP.

That is,
Client(s) <----> Main server : TCP
* One or more clients can be simultaneously connected to the main server, which
  can handle multiple requests from each of the clients at a time. 
  Each connection from the a client to the main server is implementing by creating a new
  child process using the fork() system call, everytime a new client connects via TCP
  to the main server. Hence, note that the concurrency in handling requests from multiple
  clients at the same time, is achieved via multi-processing.

* While the main server handles client requests it still keeps listening on its
  assigned static TCP PORT for any further incoming client connections for it to handle.

Main server <----> Backend servers: UDP
* Backend Servers must be running before running the main server.
* Once the main server is up and running it lets the backend servers (already running)
  know that it is "ON". The backend servers then reply with a list of countries
  handled by each of them respectively for the main server's book keeping purpose.

IP ADDRESS FAMILY: IPv4

IP ADDRESSES: For the purpose of this project, all client and the 3 server IP addresses are set to local host
(127.0.0.1). As they are all hosted on the same device.

PORTS:
* Ports used for Client and Main server communications are TCP ports.
    1) Main server : TCP PORT NO.= "33362".
    2) Client(s) : TCP PORT NO. is dynamically assigned, whenever they make a
                   new connection to the main server.
* Ports used for Main server and Backend servers communications are UDP ports.
    1) Main server: UDP PORT NO. = "32362".
    2) Backend Server A: UDP PORT NO. = "30362".
    3) Backend server B: UDP PORT NO. = "31362".
--------------------------------------------------------------------------------
*MY CODES:

NOTE: I have programmed my codes in C++ (.cpp).
All the socket libraries required by the project have been included.
The socket libraries are common for C and C++. I have also included C standard
libraries to handle char buffers and just in case if needed.
certain standard C libraries have been named as c<C library name> for their
compatibility with C++ (Ex: <cstdio> for <stdio.h>).
--------------------------------------------------------------------------------
1.) servermain.cpp

This program hosts the main server upon execution. It executes in 2 stages:

1) Bootup
* Here the main server sets up its sockets, it informs both the backend servers
  A and B (already running) that it is "ON".
* The main server then receives a response from both of the backend servers,
  with a list of all countries handled by them respectively. The main server
  stores this list in a map, mapping the backend Servers A and B to the respective
  countries handled by them.
* Once this map is constructed the main server bootup is complete and it is all
  set to listen on its TCP port for any incoming connections from the clients.

2) Client Query handling and Response to client
* Here, the main server receives the query from the clients. It acknowledges that
  the client query consists of a country name and user id. It reads the country name
  from this, after which there are 2 possible scenarios:

  a) Queried country name is neither handled by backend server A or B.
  The program will let the client know of this, by responding with an appropriate
   response to the client's query.

  b) Queried country name was found to be handled by either backend server A or B.
  The main server program then passes on the client's query (with country name and
  user id) to the respective backend server (A or B) using UDP and waits for its
  response. After receiving this response, it passes this on to the respective
  client, as the main server's response to that client's query.

NOTE: When a client program terminates. The main server acknowledges that a particular
client has disconnected and displays this on the main server screen.

NOTE: In this code the function sigchld_handler and the corresponding code segment that
calls this function to handle zombie processes have been directly referenced from
the beej's guide.

Libraries included: All C++ standard libraries, All socket libraries (as required),
<vector>, <map>, <iterator>, C standard libraries in format compatible with C++, <signal.h>
--------------------------------------------------------------------------------
2.) client.cpp
This program hosts a client upon execution. It executes in 3 stages:
1) Bootup
* Here the client program upon execution, connects to the
  main server listening on the port 33362. After being successfully connected to the
  main server, the program asks the user to enter a country name followed by a user id
  for its query.

2) Query to Main Server
* Once the user enters their query. The client program sends this to the main server
  as a request to respond back with recommendations of user ids of people in the
  queried country that can be possible friends for the person with the queried user id,
  based on data of matching interest.

NOTE: To the client it might seem that the main server has direct access to such data,
but in-fact the main server extracts this required data from other backend servers that
host such data.

3) Receiving Main Server response
* Here the clients simply receive the main server's response to their query
  previously sent and displays it on  the respective clients' screen. After this,
  the client asks the user to start a new query.

NOTE: When the main server program terminates on its end. If a client, now
sends a query to the now terminated main server, it acknowledges this, closes its
socket file descriptor and terminates the client program itself.

Libraries included: All C++ standard libraries, All socket libraries (as required),
<vector>,<iterator>, C standard libraries in format compatible with C++, <signal.h>
--------------------------------------------------------------------------------
3.) serverA.cpp
This program hosts the backend server A upon execution. It executes in 2 stages:
1) Bootup
* The backend server A boots up. It will first read the 'dataA.txt' file and store the
  data from it in its own data set. This data set has been implemented using a 2
  Dimensional map, which maps the countries handled by backend server A to various
  interest groups, which themselves are maps storing a map of various interest group
  numbers to a vector of users ID's belonging to that particular interest group number.

* Then, it waits until the main server is up and running, after which it will
  send a list of all the countries (only) it handles, to the main server.

2) Main Server Query handling and Reply
* It receives the main server query of a country name (hosted by backend server A)
  and a user id. It searches for the queried user id corresponding to the queried
  country name in its 2D Map. After this there can be 2 scenarios:

  a) Queried user id cannot be found in its data set.
     The program creates an appropriate response to let the main server
     know of this scenario.

  b) Queried user id is found in the data set.
     It makes note of all the interest groups in which the user id
     was found and constructs a vector of all the user ids (non repeating) in those
     interest groups (except queried user id of course) designating, the user ids in this
     vector are possible friends of the queried user id. It then, sends these user ids as a
     response to the main server's query.

 Libraries included: All C++ standard libraries, All socket libraries (as required),
 <vector>, <map>, <iterator>, C standard libraries in format compatible with C++, <signal.h>
--------------------------------------------------------------------------------
4.) serverB.cpp
Backend Server B follows the exactly same 2 stages as that of the Backend Server A.
The only difference being that it hosts a completely different set of countries and user ids
,as it reads from a different file, 'dataB.txt'.

Libraries included: All C++ standard libraries, All socket libraries (as required),
<vector>, <map>, <iterator>, C standard libraries in format compatible with C++, <signal.h>
--------------------------------------------------------------------------------
*FORMAT OF MESSAGES EXCHANGED:

1) Client<---> Main Server (TCP):
  a) Client Query to Main Server:
  This is the country name and user ID query from client to main server.
  b) Main Server Response to Client:
    * Appropriate response when 'Country name not found'.
    * Appropriate response when Country name found, but 'User ID Not found'.
    * Appropriate response consisting of user ids of all possible friends
      of the queried user id in the queried country.

Format: These messages are stored and exchanged as respective char buffers.

2) Main Server<----->Backend Servers(A or B):
a) Main Server to Backend Servers(A or B):
  * Main server status message :
    To let the backend servers know that main server is "ON"
  * Main server query(Country name and user id) :
    If client queried country name is found to be handled by any one of the
    backend servers, pass the client query to the respective backend server

b)Backend Servers(A or B) to Main Server:
  * Number and List of countries: Once main server is up and running, both the backend servers,
    send the no. and list of countries they host respectively for the use of the Main server.
  * Appropriate response to Main server query when queried User ID is not found.
  * Appropriate response to Main server query consisting of user ids of all possible friends
    of the queried user id in the queried country

Format: These messages are also stored and exchanged as char buffers.

NOTE: For convenience, very often char buffers were translated to and from C++ string type variables,
for easier handling and manipulation of data.
--------------------------------------------------------------------------------
*REUSED CODE:
In all 3 server codes (servermain.cpp, serverA.cpp, serverB.cpp):
I have reused a small code segment from beej's for handling zombie processes as
mentioned in the code comments.
I have also reused setsockopt() function to be able to reuse ports and avoid any
runtime errors.
Everything else is my own work.
--------------------------------------------------------------------------------
NOTE:
If a filename other than 'dataA.txt' (for serverA.cpp) or 'dataB.txt' (for serverB.cpp)
is used, the backend servers fails to read the file and deliver an appropriate message.
Incase a different filename (only name) needs to be used, it needs to be updated
in the respective code.
Apart from this small thing, no other case found where the codes fail
to execute as intended or explained above.
--------------------------------------------------------------------------------

POSSIBLE EXTENTIONS TO THE PROJECT:
(1) Implement concurrency with respect to handling multiple client requests from multiple clients using 
    multi-threading purely (or maybe a hybrid of multi-processing and multi-threading).
(2) Develop the server codes to act as web server that is able to service HTTP requests. Thereby implementing
    a multi-threaded web server.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published