https://github.com/hakimkartik/course-registration
A TCP/UDP backend server to handle student course registration, written in C
https://github.com/hakimkartik/course-registration
c cli tcp-client tcp-server terminal-based udp-server
Last synced: 3 months ago
JSON representation
A TCP/UDP backend server to handle student course registration, written in C
- Host: GitHub
- URL: https://github.com/hakimkartik/course-registration
- Owner: hakimkartik
- Created: 2023-01-14T05:56:30.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2023-01-14T05:57:55.000Z (over 3 years ago)
- Last Synced: 2025-01-19T20:17:33.178Z (over 1 year ago)
- Topics: c, cli, tcp-client, tcp-server, terminal-based, udp-server
- Language: C++
- Homepage:
- Size: 27.3 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme.html
Awesome Lists containing this project
README
readme
EE450 Project
Name: Kartik Hakim
USC ID: 9520-8829-28
Extra Credit Section : Done
Project flow chart:
#mermaid-svg-v0g0KnBpUUrk47XC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#000000;}#mermaid-svg-v0g0KnBpUUrk47XC .error-icon{fill:#552222;}#mermaid-svg-v0g0KnBpUUrk47XC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-v0g0KnBpUUrk47XC .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-v0g0KnBpUUrk47XC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-v0g0KnBpUUrk47XC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-v0g0KnBpUUrk47XC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-v0g0KnBpUUrk47XC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-v0g0KnBpUUrk47XC .marker{fill:#666;stroke:#666;}#mermaid-svg-v0g0KnBpUUrk47XC .marker.cross{stroke:#666;}#mermaid-svg-v0g0KnBpUUrk47XC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-v0g0KnBpUUrk47XC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#000000;}#mermaid-svg-v0g0KnBpUUrk47XC .cluster-label text{fill:#333;}#mermaid-svg-v0g0KnBpUUrk47XC .cluster-label span{color:#333;}#mermaid-svg-v0g0KnBpUUrk47XC .label text,#mermaid-svg-v0g0KnBpUUrk47XC span{fill:#000000;color:#000000;}#mermaid-svg-v0g0KnBpUUrk47XC .node rect,#mermaid-svg-v0g0KnBpUUrk47XC .node circle,#mermaid-svg-v0g0KnBpUUrk47XC .node ellipse,#mermaid-svg-v0g0KnBpUUrk47XC .node polygon,#mermaid-svg-v0g0KnBpUUrk47XC .node path{fill:#eee;stroke:#999;stroke-width:1px;}#mermaid-svg-v0g0KnBpUUrk47XC .node .label{text-align:center;}#mermaid-svg-v0g0KnBpUUrk47XC .node.clickable{cursor:pointer;}#mermaid-svg-v0g0KnBpUUrk47XC .arrowheadPath{fill:#333333;}#mermaid-svg-v0g0KnBpUUrk47XC .edgePath .path{stroke:#666;stroke-width:1.5px;}#mermaid-svg-v0g0KnBpUUrk47XC .flowchart-link{stroke:#666;fill:none;}#mermaid-svg-v0g0KnBpUUrk47XC .edgeLabel{background-color:white;text-align:center;}#mermaid-svg-v0g0KnBpUUrk47XC .edgeLabel rect{opacity:0.5;background-color:white;fill:white;}#mermaid-svg-v0g0KnBpUUrk47XC .cluster rect{fill:hsl(210,66.6666666667%,95%);stroke:#26a;stroke-width:1px;}#mermaid-svg-v0g0KnBpUUrk47XC .cluster text{fill:#333;}#mermaid-svg-v0g0KnBpUUrk47XC .cluster span{color:#333;}#mermaid-svg-v0g0KnBpUUrk47XC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(-160,0%,93.3333333333%);border:1px solid #26a;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-v0g0KnBpUUrk47XC:root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-v0g0KnBpUUrk47XC flowchart{fill:apa;}tcpServerPort:25928
udpClientPort:24928udpServerPort:21928udpServerPort:23928udpServerPor:22928clientserverMserverCserverCSserverEE
What have I done in this assignment?
In this socket-programming project using CPP language, I implemented the simulation of a web registration process.
In this process, a client will enter the course code and category of the information he/she wishes to retrieve.
This client will communicate with serverM process, which in turn will communicate with credential (serverC) and backend servers (serverEE, serverCS) .
I tested all code both on my local Mac (M2 chip) and studentVM (ubuntu 16).
Comments
Idiosyncrasies of the project
Please keep following suggestions in mind while testing:
-
Please prefer reading from readme.html.
-
If while testing client is stopped or gets stuck, please restart all processes, it should start working fine.
-
Please make sure course-ids are inputted in the syntax mentioned in How to run the programs section
-
If while testing, authentication is failing, please restart client, serverM and serverC.
-
If serverM exits with following error
libc++abi: terminating with uncaught exception of type std::out_of_range: basic_string
zsh: abort ./serverM
Please restart client , serverCand serverM processes.
- Sometimes the I/O buffers will not read properly, so the messages will not be printed properly on the console.
james sent a request to the main server.
The client received the response from the Main server using TCP over port 52446.
.he CourseName of EE450 is Introduction to Computer Networks
The ServerEE received a request from the Main Server about the CourseName of EE450.
The course information has been found: The CourseName of EE450 is Introduction to . mputer Networks
The ServerEE finished sending the response to the Main Server.
It should get fixed by restarting all 5 processes.
How to run the programs
Please start the 5 processes in following format:-
-
First open 5 different terminal window instances.
-
Use one terminal and type make all to compile all the cpp files.
ee450_hakim_kartik_9520882928 % make all
g++ -std=c++11 -shared-libgcc serverM.cpp -o serverM
g++ -std=c++11 -shared-libgcc serverC.cpp -o serverC
g++ -std=c++11 -shared-libgcc serverEE.cpp -o serverEE
g++ -std=c++11 -shared-libgcc serverCS.cpp -o serverCS
g++ -std=c++11 -shared-libgcc client.cpp -o client
ee450_hakim_kartik_9520882928 %
- Start the processes in following order
Terminal 1: ./serverEE
Terminal 2: ./serverCS
Terminal 3: ./serverC
Terminal 4: ./serverM
Terminal 5: ./client
- Input syntax in terminal 1, for client process:
- While entering username and password:
ee450_hakim_kartik_9520882928 % ./client
The client is up and running.
Please enter the username: james
Please enter the password: Th!r3oe4s
james sent an authentication request to the main server.
james received the result of authentication using TCP over port 51750. Authentication failed: Password does not match.
Attempts remaining: 2
Please enter the username: amber
Please enter the password: cOntra4@positiv1e
amber sent an authentication request to the main server.
amber received the result of authentication using TCP over port 51759. Authentication failed: Password does not match.
Attempts remaining: 1
Please enter the username: james
Please enter the password: 2kAnsa7s)
james sent an authentication request to the main server.
james received the result of authentication using TCP over port 51767. Authentication is successful
- While entering single course-ids
Please enter the course code to query: EE450
Please enter the category(Credit / Professor / Days / CourseName): Days
james sent a request to the main server.
The client received the response from the Main server using TCP over port 51767.
The Days of EE450 is Tue;Thu
- While entering multiple course-ids
Please enter the course code to query: EE450 CS100 EE520
james sent a request to the main server.
The client received the response from the Main server using TCP over port 52001.
CourseCode: Credits, Professor, Days, Course Name
EE450: 4,Ali Zahid,Tue;Thu,Introduction to Computer Networks
CS100: 4,Sathyanaraya Raghavachary,Tue;Thu,Explorations in Computing
EE520: 4,Todd Brun,Tue;Thu,Introduction to Quantum Information Processing
Incorrect way of input
-
DO NOT ENTER UNEXPECTED SPACES
-
END ALL LINES USING NEWLINE CHARACTERS
Please enter the course code to query: EE450 CS100
EE520
james sent a request to the main server.
The client received the response from the Main server using TCP over port 52029.
CourseCode: Credits, Professor, Days, Course Name
EE450: 4,Ali Zahid,Tue;Thu,Introduction to Computer Networks
CS100: 4,Sathyanaraya Raghavachary,Tue;Thu,Explorations in Computing
EE520: 4,Todd Brun,Tue;Thu,Introduction to Quantum Information Processing
Please enter the course code to query: EE450
EE520
james sent a request to the main server.
The client received the response from the Main server using TCP over port 52030.
CourseCode: Credits, Professor, Days, Course Name
EE450: 4,Ali Zahid,Tue;Thu,Introduction to Computer Networks
EE520: 4,Todd Brun,Tue;Thu,Introduction to Quantum Information Processing
-----Start a new request-----
Please enter the course code to query:
Implementations
What your code files are and what each one of them does
client
The workflow of client is as follows:
-
client process start a TCP socket and uses a dynamically assigned port number.
-
Enter the username and password.
-
The given username and password (say u1,p1), are appended in a string template username:<u1>,password:<p1>.
-
This template is sent via TCP to serverM.
-
The serverM checks with serverC and responds, via TCP, one of the following strings as response:
* Username not found
* Username found, Password didnt match
* Username verified
* Not sure
-
If the response is Username verified, client will expect to read course and category and code will move to steps 7-10.
If the response is not Username verified, steps 1-6 will be repeated.
-
User will enter course code and category(expected values are Credit / Professor / Days / CourseName ), say c1 and c2.
-
Will create a string template course:<c1>,category:<c2> and send to serverM via TCP.
-
serverM will check with respective backend servers, via UDP, and responds either with the requested information (if the course-code is present in DB) or with string NO_DATA (if the course-code is not present in DB).
-
client will process the response from serverM, via TCP, and print appropriate messages on the console.
serverM
The workflow of serverMis as follows:
-
serverM expects to receive a string template of format username:<u1>,password:<p1> from client via TCP over port 25928.
-
serverM extracts the username, u1 and password, p1 from the template and encrypts them.
-
The encrypted username and password, say e1 and e2, are sent to serverC via UDP over port 24928.
-
serverC replies, via UDP, with one of the following strings:
* Username not found
* Username found, Password didnt match
* Username verified
* Not sure
-
serverM forwards these response from serverC to client, via TCP.
-
If the serverC, response is Username verified, a flag is set, to expect course-category string template, from client.
-
Once the flag is set, serverM receives client-category template from client.
-
serverM will extract course and category, say c1 and c2, and based on the first 2 characters of course c1 will choose appropriate backend servers.
-
serverM will send the string template course:<c1>,category:<c2> to backend servers (serverCS or serverEE) via UDP over port, 24928.
-
Once serverM receives the response, it forwards it to client, via TCP over port 25928.
serverC
The workflow of serverC is as follows:
-
serverC expects a string containing u1,p1 via UDP over port 21928.
-
serverC reads the txt file cred.txt and stores in a global map variable.
-
Once we receive the string, we extract u1 and p1 and look for u1 as a key in the global map.
-
If u1 is found in the map, we check p1 is similar to password stored in map.
-
Based on both the comparison, a string response is selected:
* Username not found
* Username found, Password didnt match
* Username verified
* Not sure
-
This string response is replied back to serverM.
serverCS/EE
The workflow of backend servers (serverEE/serverCS) is as follows:
-
serverEE/CS expects a string containing course:<c1>,category:<c2> via UDP over port 23928(serverEE) or port 22928(serverCS) from serverM.
-
serverEE/CS reads the txt file ee.txt (serverEE) or cs.txt (serverCS) and stores in 4 global map variables (credit / professor name/ course name / credits).
-
Once we receive the string, we extract course id, c1, and course category, c2.
-
Based on c2, category, we select the appropriate map variable, search for course id c1, and store the response as string.
-
If course code is not found, we set the response to NOT_FOUND.
-
We reply back the response to serverM.
-
For extra credit section, I set category to everything and read information from all 4 global variable maps and append them in the response variable .
Message Formats
code
UserName / Password
CourseCategory
client
username:u1,password:p1
course:c1,category:c2
serverM
username:eU1,password:eP1
course:c1,category:c2
serverC
username:eU1,password:eP1
NA
serverCS
NA
c1,c2
serverEE
NA
c1,c2
where:
u1 : username entered on client terminal
p1 : password enter on client terminal
eU1: encrypted username sent by serverM to serverC
eP1 : encrypted password sent by serverM to serverC
c1 : course id entered on client terminal sent by client to serverM to backend servers
c2 : course category entered on client terminal by client to serverM to backend servers
Reused Code
For example
from section 6.5:-
int sockfd, rv, numbytes;
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr;
socklen_t addr_len;
char s[INET6_ADDRSTRLEN];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
//hints.ai_flags = AI_PASSIVE; // use my IP
hints.ai_flags = INADDR_ANY; // using localhost as IP
if ((rv = getaddrinfo(NULL, MY_UDP_PORT, &hints, &servinfo)) != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
exit(2);
}
// loop through all the results and bind to the first we can
for (p = servinfo; p != NULL; p = p->ai_next)
{
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
{
perror("serverEE : socket");
continue;
}
if (::bind(sockfd, p->ai_addr, p->ai_addrlen) == -1)
{
close(sockfd);
perror("bind failed in serverEE, will try another socket");
continue;
}
break;
}
if (p == NULL)
{
fprintf(stderr, "bind failed in serverEE\n");
exit(2);
}
freeaddrinfo(servinfo);
For example:-
read(newsockfd,buffer,255)
if (connect(sockfd,&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
int sockfd = socket(domain, type, protocol) ;
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) ;
int new_socket= accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
vector<string> result;
stringstream s_stream(my_str); //create string stream from the string
while (s_stream.good())
{
string substr;
getline(s_stream, substr, ','); //get first string delimited by comma
result.push_back(substr);
}
void ltrim(string &s) {
s.erase(s.begin(), find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
}
// trim from end (in place)
void rtrim(string &s) {
s.erase(find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}
// trim from both ends (in place)
void trim(string &s) {
ltrim(s);
rtrim(s);
}
Extra files
-
stringUtil.h : custom header file having string trimming code for given input string.
-
codec.h : custom header having encryption / decryption code for credential verification.