in c++ code, the zip file is what it being asked, need a client.cpp file and a server.cpp file. below has some code example given that can be used but needs to be commented “code from given file”
Objective:
This assignment will introduce you to interprocess communication mechanisms in UNIX using sockets.
Problem:
You must write two programs to implement a distributed version of the multithreaded program you created for programming assignment 1. These programs should find the positions of the symbols in the original message, reconstruct the original message (based on the encoded message), and determine the number of bits required to represent the positions using Elias-Gamma encoding.
These programs are:
The server program:
The user will execute this program using the following syntax:
./exec_filename port_no
where exec_filename is the name of your executable file, and port_no is the port number to create the socket. The port number will be available to the server program as a command-line argument.
The server program receives no input from STDIN and prints no messages to STDOUT.
The server program executes the following task:
-
Receive multiple requests from the client program using sockets. Therefore, the server program creates a child process for each request to handle them simultaneously. For this reason, the parent process must handle zombie processes by implementing the fireman() function call (unless you can determine the number of requests the server program receives from the client program).
Each child process executes the following tasks:
-
-
Receive the encoded message, the assigned symbol, and the sum of the frequencies for the symbols assigned to the previous threads on the client program.
-
Determines the positions of the assigned symbol in the original message.
-
Calculates the number of bits used to represent the symbol’s position using Elias Gamma encoding.
-
Send the positions and the number of bits used to represent the symbol’s positions to the client program using sockets.
-
The client program:
The user will execute this program using the following syntax:
./exec_filename hostname port_no < input_filename
where exec_filename is the name of your executable file, hostname is the address where the server program is located, port_no is the port number used by the server program, and input_filename is the name of the input file. The hostname and the port number will be available to the client as command-line arguments.
The client program receives multiline input in accordance with the specifications for Programming Assignment 1.
Input example:
4
A 5
C 2
B 2
D 3
10100010000010000001010001100011100010010010100010110110001100
After reading the information from STDIN, the program must create n child threads (where n is the alphabet size). Each child thread executes the following tasks:
-
Receives the encoded message, the symbol to decode, and the information needed to find the positions of the assigned symbol in the encoded message.
-
Send the received information to the server program using sockets.
-
Receive the positions and number of bits used to represent the symbol’s positions from the server program using sockets.
-
Store the received information in a memory location accessible by the main thread.
-
Stores the assigned symbol, using the determined positions, into the memory address shared with the main thread that contains the decoded message.
Finally, the main thread prints the information for each symbol to STDOUT (sorted according to the compression algorithm rules) and the decoded message.
The expected output (given the input above) is:
Symbol: A, Frequency: 5
Positions: 0 1 3 7 9
Bits to represent the position(s): 23
Symbol: D, Frequency: 3Positions: 5 6 8 Bits to represent the position(s): 17
Symbol: B, Frequency: 2Positions: 4 10 Bits to represent the position(s): 12
Symbol: C, Frequency: 2Positions: 2 11 Bits to represent the position(s): 10
Decoded message: AACABDDADABC
Notes:
- The position values for the symbols must start from 1 (not 0), since Elias Gamma can only represent positive integers starting from 1.
- You can safely assume that the input will always be in the proper format.
- You must use the output statement format based on the example above.
- For the client program, you must use POSIX Threads and stream sockets. A penalty of 100% will be applied to submissions not using POSIX Threads and Stream Sockets.
- For the server program, you must use multiple processes (fork) and stream sockets. Submissions that do not use multiple processes and Stream Sockets will be penalized by 100%.
- The Moodle server will kill your server program after executing each test case.
- You must present code that is readable and has comments explaining the logic of your solution. A 10% penalty will be applied to submissions that do not follow this guideline.
- You cannot use global variables. A 100% penalty will be applied to submissions using global variables.
- A 100% penalty will be applied to solutions that do not compile.
- A 100% penalty will be applied to solutions that hardcode the output.
RUBRIC:
- 10 points for each test case (20 points total)
- 10 points for presenting clean and readable code.
- 10 points for using the fireman function correctly, or a for loop based on the number of requests.
- 10 points for reading information from STDIN (client).
- 25 points if each request to the server:
- Receives information from the client program and creates a child process per request (5 points).
- Generates the request information (positions and the number of bits used to represent them with Elias Gamma). (10 points).
- Return the information to the client program (5 points).
- Closes the socket (5 points).
- 25 points if each child thread:
- Creates a socket to communicate with the server (5 points).
- Sends and receives information to/from the server (10 points).
- Stores the information in a memory location accessible by the main thread (5 points).
- Closes the socket (5 points).
ADDITIONAL PENALTIES:
100 points off for a solution not compiling (in addition to test cases not passing)
100 points off for lack of generalized solution (hard-coding, no server file, etc.)
100 points off for not using POSIX threads, fork(), or Sockets.
100 points for using global variables.
// Hostname = 172.25.215.151, port = 3360
/*
struct student
{
char name[20];
int psid;
int grade;
};
*/
this is an example of a server.cpp file
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
struct student
{
char name[20];
int psid;
int grade;
};
// Fireman function
void fireman(int)
{
while (waitpid(-1, NULL, WNOHANG) > 0);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
struct sockaddr_in serv_addr, cli_addr;
int n;
// Creating a signal to execute the fireman function when a child process end its execution
signal(SIGCHLD, fireman);
// Check for the port number from the command line
if (argc < 2)
{
std::cerr << “ERROR, no port providedn”;
exit(1);
}
//Create a socket descriptor
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
std::cerr << “ERROR opening socket”;
exit(1);
}
//Populate the sockaddr_in structure
bzero((char *)&serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
// Bind the socket descriptor with the sockaddr_in structure
if (bind(sockfd, (struct sockaddr *)&serv_addr,
sizeof(serv_addr)) < 0)
{
std::cerr << “ERROR on binding”;
exit(1);
}
// Set the maximum number of concurrent connections
listen(sockfd, 20);
clilen = sizeof(cli_addr);
while (true)
{
// Accept a request from the client. A new socket descriptor is created to handle the request
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, (socklen_t *)&clilen);
// Create a child process to answer the request.
if (fork() == 0)
{
if (newsockfd < 0)
{
std::cerr << “ERROR on accept”;
exit(1);
}
student s;
n = read(newsockfd, &s, sizeof(student));
if (n < 0)
{
std::cerr << “ERROR reading from socket”;
exit(1);
}
std::cout << “Name: ” << s.name << std::endl;
std::cout << “PSID: ” << s.psid << std::endl;
std::cout << “Grade: ” << s.grade << std::endl;
//Close the newsocket descriptor
close(newsockfd);
// Terminate the child process
_exit(0);
}
}
close(sockfd);
return 0;
}
and below is example of client.cpp
#include <unistd.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
struct student
{
char name[20];
int psid;
int grade;
};
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
// Checking for the hostname and port number from the command line.
if (argc < 3)
{
std::cerr << “usage ” << argv[0] << “hostname portn”;
exit(0);
}
// Creating a socket descriptor
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
std::cerr << “ERROR opening socket”;
// Storing the hostname information
server = gethostbyname(argv[1]);
if (server == NULL)
{
std::cerr << “ERROR, no such hostn”;
exit(0);
}
// Transforming the port number to int
portno = atoi(argv[2]);
// Populating the sockaddr_in structure
bzero((char *)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
// Connecting to the server
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
std::cerr << “ERROR connecting”;
exit(1);
}
// Sending a symbol
student s = {“Carlos Rincon”,1234,100};
n = write(sockfd, &s, sizeof(student));
if (n < 0)
{
std::cerr << “ERROR writing to socket”;
exit(1);
}
// Closing the socket
close(sockfd);
return 0;
}
Leave a Reply
You must be logged in to post a comment.