CS4448/5550 Project 1: Multithreaded Webserver
*************************************************************************************
The project is done by a group of two or three students.
Submission Details
Due Date: 15th March, 2015, 11:59PM (Hard Deadline)
You are to submit a zip file through blackboard only (no email submission will be accepted) that
includes project document and copy all of your server source files (*.c and *.h) and a Makefile.
Project document will include following:
Introduction: introduce your project here in a few paragraph
Design overview: A few simple paragraphs describing the overall structure of your code
and any important structures.
Complete specification: Describe how you handled any ambiguities in the specification.
For example, how do you implement the ANY policy?
Known bugs or problems: A list of any features that you did not implement or that you
know are not working correctly.
Testing: Describe how you tested the functionality of your web server. Describe how can
you use the various versions of your extended client to see if the server is handing
requests concurrently and implementing the FIFO, HPSC, or HPDC policies.
*************************************************************************************
In this project, you will design a multithreaded webserver in C on Unix/Linux Platform.
Your server program should run as follows:
server [portnum] [threads] [buffers] [schedalg]
The command line arguments to your web server are to be interpreted as follows.
portnum:
the port number that the web server should listen on; the basic web server
already handles this argument.
threads: the number of worker threads that should be created within the web server.
Must be a positive integer.
buffers: the number of request connections that can be accepted at one time. Must be a
positive integer. Note that it is not an error for more or less threads to be created than
buffers.
schedalg: the scheduling algorithm to be performed. Must be one of ANY, FIFO,
HPSC, or HPDC.
For example, if you run your program as
server 5003 8 16 FIFO
Phase 1: Design a simple http webserver.
A Brief Overview of HTTTP:
Web browsers and web servers interact using a text-based protocol called HTTP (Hypertext Transfer
Protocol). A web browser opens an Internet connection to a web server and requests some content with
HTTP. The web server responds with the requested content and closes the connection. The browser
reads the content and displays it on the screen.
Each piece of content on the server is associated with a file. An HTTP request (from the web browser to
the server) consists of a request line, followed by zero or more request headers, and finally an empty
text line. A request line has the form: method uri version. The method is usually GET (but may be other
things, such as POST, OPTIONS, or PUT). The uri is the file name and any optional arguments (for
dynamic content). Finally, the version indicates the version of the HTTP protocol that the web client is
using (e.g., HTTP/1.0 or HTTP/1.1).
An HTTP response (from the server to the browser) is similar; it consists of a response line, zero or more
response header lines, an empty text line, and finally the interesting part, the response body. A
response line has the form version status message. The status is a three-digit positive integer that
indicates the state of the request; some common states and the corresponding messages are 200 for
OK, 403 for Forbidden, and 404 for Not found. Two important lines in the response header are ContentType, which tells the client the MIME type of the content in the response body (e.g., html or gif) and
Content-Length, which indicates its size in bytes. The server can add any custom header line.
You have to design a simple http webserver that would process web request for atleast Get and head
(You may choose to include more methods such as PUT, POSTS etc.)
Follow http specification from here: http://tools.ietf.org/html/rfc7230
Phase 2: Multithreaded Server
Single-threaded web servers suffer from a fundamental performance problem in that only a
single HTTP request can be serviced at a time. Thus, every other client that is accessing this web
server must wait until the current http request has finished; the most important extension that you
will be adding is to make the basic web server multi-threaded.
The server will consist of 2+n threads. The first two threads will do following jobs:
Thread 1: Thread 1 will be responsible for listening to incoming http connection and inserting
them into a fixed size queue. This thread is a main thread that also creates a pool of n worker
threads.
Thread 2: will be responsible for choosing a thread from the ready queue and scheduling it to
one of the worker thread.
n-worker threads: A pool of n worker threads will serve the incoming requests. The number n is
given as a parameter when the webserver starts. Each worker thread is able to handle both static
and dynamic requests. A worker thread wakes when there is an http request in the queue; when
there are multiple http requests available, which request is handled depends upon the scheduling
policy. The worker thread then waits for another http request.
Scheduling:
Note that when your web server has multiple worker threads running (the number of which is
specified on the command line), you will not have any control over which thread is actually
scheduled at any given time by the OS. Your role in scheduling is to determine which http
request should be handled by each of the waiting worker threads in your web server.
The scheduling policy is determined by a command line argument when the web server is started
and are as follows:
Any Concurrent Policy (ANY):
When a worker thread wakes, it can handle any
request in the buffer. The only requirement is that all threads are handling requests
concurrently. (In other words, you can make ANY=FIFO if you have FIFO working.)
First-in-First-out (FIFO): When a worker thread wakes, it handles the first request
(i.e., the oldest request) in the buffer. Note that the http requests will not necessarily
finish in FIFO order since multiple threads are running concurrently; the order in which
the requests complete will depend upon how the OS schedules the active threads.
Highest Priority to Static Content (HPSC): When a worker thread wakes, it
handles the first request that is static content; if there are no requests for static content, it
handles the first request for dynamic content. Note that this algorithm can lead to the
starvation of requests for dynamic content.
Highest Priority to Dynamic Content (HPDC): When a worker thread wakes, it
handles the first request that is dynamic content; if there are no requests for dynamic
content, it handles the first request for static content. Note that this algorithm can lead to
the starvation of requests for static content.
Important notes:
You should investigate how to create and manage posix threads with pthread_create
and pthread_detach.
The master threads and the worker threads are in a producer-consumer relationship and
require that their accesses to the shared buffer be synchronized. Specifically, the master
thread must block and wait if the buffer is full; a worker thread must wait if the buffer is
empty. In this project, you are required to use condition variables. If your
implementation performs any busy-waiting (or spin-waiting) instead, you will be
heavily penalized.
HPSC and SPDC policies require that something be known about each request before the
requests can be scheduled. Thus, to support this scheduling policy, you will need to do
some initial processing of the request outside of the worker threads; you will want the
master thread to perform this work, which requires that it read from the network
descriptor.
CS4448/5550 Project 1: Multithreaded Webserver
*************************************************************************************
The project is done by a group of two or three students.
Submission Details
Due Date: 15th March, 2015, 11:59PM (Hard Deadline)
You are to submit a zip file through blackboard only (no email submission will be accepted) that
includes project document and copy all of your server source files (*.c and *.h) and a Makefile.
Project document will include following:
Introduction: introduce your project here in a few paragraph
Design overview: A few simple paragraphs describing the overall structure of your code
and any important structures.
Complete specification: Describe how you handled any ambiguities in the specification.
For example, how do you implement the ANY policy?
Known bugs or problems: A list of any features that you did not implement or that you
know are not working correctly.
Testing: Describe how you tested the functionality of your web server. Describe how can
you use the various versions of your extended client to see if the server is handing
requests concurrently and implementing the FIFO, HPSC, or HPDC policies.
*************************************************************************************
In this project, you will design a multithreaded webserver in C on Unix/Linux Platform.
Your server program should run as follows:
server [portnum] [threads] [buffers] [schedalg]
The command line arguments to your web server are to be interpreted as follows.
portnum:
the port number that the web server should listen on; the basic web server
already handles this argument.
threads: the number of worker threads that should be created within the web server.
Must be a positive integer.
buffers: the number of request connections that can be accepted at one time. Must be a
positive integer. Note that it is not an error for more or less threads to be created than
buffers.
schedalg: the scheduling algorithm to be performed. Must be one of ANY, FIFO,
HPSC, or HPDC.
For example, if you run your program as
server 5003 8 16 FIFO
Phase 1: Design a simple http webserver.
A Brief Overview of HTTTP:
Web browsers and web servers interact using a text-based protocol called HTTP (Hypertext Transfer
Protocol). A web browser opens an Internet connection to a web server and requests some content with
HTTP. The web server responds with the requested content and closes the connection. The browser
reads the content and displays it on the screen.
Each piece of content on the server is associated with a file. An HTTP request (from the web browser to
the server) consists of a request line, followed by zero or more request headers, and finally an empty
text line. A request line has the form: method uri version. The method is usually GET (but may be other
things, such as POST, OPTIONS, or PUT). The uri is the file name and any optional arguments (for
dynamic content). Finally, the version indicates the version of the HTTP protocol that the web client is
using (e.g., HTTP/1.0 or HTTP/1.1).
An HTTP response (from the server to the browser) is similar; it consists of a response line, zero or more
response header lines, an empty text line, and finally the interesting part, the response body. A
response line has the form version status message. The status is a three-digit positive integer that
indicates the state of the request; some common states and the corresponding messages are 200 for
OK, 403 for Forbidden, and 404 for Not found. Two important lines in the response header are ContentType, which tells the client the MIME type of the content in the response body (e.g., html or gif) and
Content-Length, which indicates its size in bytes. The server can add any custom header line.
You have to design a simple http webserver that would process web request for atleast Get and head
(You may choose to include more methods such as PUT, POSTS etc.)
Follow http specification from here: http://tools.ietf.org/html/rfc7230
Phase 2: Multithreaded Server
Single-threaded web servers suffer from a fundamental performance problem in that only a
single HTTP request can be serviced at a time. Thus, every other client that is accessing this web
server must wait until the current http request has finished; the most important extension that you
will be adding is to make the basic web server multi-threaded.
The server will consist of 2+n threads. The first two threads will do following jobs:
Thread 1: Thread 1 will be responsible for listening to incoming http connection and inserting
them into a fixed size queue. This thread is a main thread that also creates a pool of n worker
threads.
Thread 2: will be responsible for choosing a thread from the ready queue and scheduling it to
one of the worker thread.
n-worker threads: A pool of n worker threads will serve the incoming requests. The number n is
given as a parameter when the webserver starts. Each worker thread is able to handle both static
and dynamic requests. A worker thread wakes when there is an http request in the queue; when
there are multiple http requests available, which request is handled depends upon the scheduling
policy. The worker thread then waits for another http request.
Scheduling:
Note that when your web server has multiple worker threads running (the number of which is
specified on the command line), you will not have any control over which thread is actually
scheduled at any given time by the OS. Your role in scheduling is to determine which http
request should be handled by each of the waiting worker threads in your web server.
The scheduling policy is determined by a command line argument when the web server is started
and are as follows:
Any Concurrent Policy (ANY):
When a worker thread wakes, it can handle any
request in the buffer. The only requirement is that all threads are handling requests
concurrently. (In other words, you can make ANY=FIFO if you have FIFO working.)
First-in-First-out (FIFO): When a worker thread wakes, it handles the first request
(i.e., the oldest request) in the buffer. Note that the http requests will not necessarily
finish in FIFO order since multiple threads are running concurrently; the order in which
the requests complete will depend upon how the OS schedules the active threads.
Highest Priority to Static Content (HPSC): When a worker thread wakes, it
handles the first request that is static content; if there are no requests for static content, it
handles the first request for dynamic content. Note that this algorithm can lead to the
starvation of requests for dynamic content.
Highest Priority to Dynamic Content (HPDC): When a worker thread wakes, it
handles the first request that is dynamic content; if there are no requests for dynamic
content, it handles the first request for static content. Note that this algorithm can lead to
the starvation of requests for static content.
Important notes:
You should investigate how to create and manage posix threads with pthread_create
and pthread_detach.
The master threads and the worker threads are in a producer-consumer relationship and
require that their accesses to the shared buffer be synchronized. Specifically, the master
thread must block and wait if the buffer is full; a worker thread must wait if the buffer is
empty. In this project, you are required to use condition variables. If your
implementation performs any busy-waiting (or spin-waiting) instead, you will be
heavily penalized.
HPSC and SPDC policies require that something be known about each request before the
requests can be scheduled. Thus, to support this scheduling policy, you will need to do
some initial processing of the request outside of the worker threads; you will want the
master thread to perform this work, which requires that it read from the network
descriptor.
/* A simple server in the internet domain using TCP
The port number is passed as an argument */
#include
#include
#include
#include
#include
#include
#include
#define MAXCONNECTION 100 // maximum number of simultaneously connection allowed
const char CONTENTDIR[]="./contentdir" ; // this is the directory where keep all the files for
requests
void error(const char *msg)
{
perror(msg);
exit(1);
}
void httpWorker(int *);// This function will handle request
char * fType(char *);
char * responseHeader(int, char *);// function that builds response header
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
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);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,MAXCONNECTION);
while(1){
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) error("ERROR on accept");
httpWorker(&newsockfd);//worker to fulfillthe request
}
close(sockfd);
return 0;
}
void httpWorker(int *sockfd){//sockfd contains all the information
int newsockfd = *sockfd;// create a local variable for sockfd
char buffer[256];// we will read the data in this buffer
char *token;// local variable to split the request to get the filename
bzero(buffer,256);// intialize the buffer data to zero
char fileName[50];
char homedir[50];
char * type;
strcpy(homedir,CONTENTDIR);// directory where files are stored.
char *respHeader; //response header
// start reading the message from incoming conenction
if (read(newsockfd,buffer,255) < 0) error("ERROR reading from socket");
//get the requested file part of the request
token = strtok(buffer, " ");// split string into token seperated by " "
token = strtok(NULL, " ");// in this go we read the file name that needs to be sent
strcpy(fileName,token);
// get the complete filename
if(strcmp(fileName,"/")==0) // if filename is not provided then we will send index.html
strcpy(fileName,strcat(homedir,"/index.html"));
else
strcpy(fileName,strcat(homedir,fileName));
type = fType(fileName);// get file type
//open file and ready to send
FILE *fp;
int file_exist=1;
fp=fopen(fileName, "r");
if (fp==NULL) file_exist=0;
respHeader = responseHeader(file_exist,type);
if ((send(newsockfd, respHeader,strlen(respHeader), 0) == -1) || (send(newsockfd,"\r\n",
strlen("\r\n"), 0) == -1))
perror("Failed to send bytes to client");
free(respHeader);// free the allocated memory (note: the memory is allocated in
responseheader function)
if (file_exist){
char filechar[1];
while((filechar[0]=fgetc(fp))!=EOF){
if(send(newsockfd,filechar,sizeof(char),0) == -1) perror("Failed to send bytes to client");
}
}
else{
if (send(newsockfd," 404 Not FoundNot
Found \r\n", 100, 0) == -1)
perror("Failed to send bytes to client");
}
close(newsockfd);
}
// function below find the file type of the file requested
char * fType(char * fileName){
char * type;
char * filetype = strrchr(fileName,'.');// This returns a pointer to the first occurrence of
some character in the string
if((strcmp(filetype,".htm"))==0 || (strcmp(filetype,".html"))==0)
type="text/html";
else if((strcmp(filetype,".jpg"))==0)
type="image/jpeg";
else if(strcmp(filetype,".gif")==0)
type="image/gif";
else if(strcmp(filetype,".txt")==0)
type="text/plain";
else
type="application/octet-stream";
return type;
}
//buildresponseheader
char * responseHeader(int filestatus, char * type){
char statuscontent[256] = "HTTP/1.0";
if(filestatus==1){
strcat(statuscontent," 200 OK\r\n");
strcat(statuscontent,"Content-Type: ");
strcat(statuscontent,type);
strcat(statuscontent,"\r\n");
}
else {
strcat(statuscontent,"404 Not Found\r\n");
//send a blank line to indicate the end of the header lines
strcat(statuscontent,"Content-Type: ");
strcat(statuscontent,"NONE\r\n");
}
char * returnheader =malloc(strlen(statuscontent)+1);
strcpy(returnheader,statuscontent);
return returnheader;
}
Purchase answer to see full
attachment