Click here to Skip to main content
15,884,177 members
Articles / Desktop Programming / MFC
Article

Multithreaded server class with example of HTTP server

Rate me:
Please Sign up or sign in to vote.
4.78/5 (27 votes)
12 Aug 20014 min read 187.4K   10.4K   86   27
Multithreaded server class with example of HTTP server

Introduction

This article covers the following topics

  • Win32 Threads
  • Synchronization objects
  • Asynchronous sockets
  • Basic HTTP protocol
  • Using abstract classes
  • STL

Details

When writing a socket server, I had to choose between using a Single Thread technique and using a Multithread technique. I discovered the Multithread technique has several advantages, including the following:
  • No effort is required to overcome with 64 handles when using WSAWaitForMultipleObjects(...).
  • No effort is required to overcome passing through big files to the client without delaying other requests.
Although these advantages make Multithread Servers appropriate in many situations, they do not justify the use of Multithread Servers always and everywhere. For example, if a computer carries a server component that is not very powerful, using a Static Thread solution may be the best choice. The following article describes an implementation of a Multithread Server based on Asynchronous sockets. I built a web server as an example using my server class as a base. The implementation of HTTP is just to serve basic HTTP requests. So let's go through some details of implementation.

Implementation

There are number of threads that are always alive and waiting or processing something. The first important thread is the AcceptThread. Its responsibility is to initialize socket library and listen to all incoming connections. Each time a new connection arrives a new thread is created. This new thread is called the ClientThread, and its responsibility is to take care of the needs of the newly connected client. When the client has disconnected, the request to close the thread's handle will be passed to the HelperThread through the HandleList object.

Next I'll describe what some of the important functions in the CGenericServer class is designed for. The functions appear in the order in which they are implemented in sources.

  • GetStats(...) - Returns useful statistics about how much traffic is present, how many visitors with unique IP addresses have been connected, how many total requests to the server have taken place, and how many clients are currently connected to the server.

  • AddClient(...) - Notifies the derived class about new connection arrivals, and creates a working thread for serving child socket needs.

  • Run(...) - Launches Accept and Helper threads.

  • Shutdown(...) - Kills Accept and Helper threads and waits until ClientThreads also are killed.

  • Reset(...) - Resets statistics values to 0.

  • CleanupThread(...) - Cleans up all opened handles and allocated memory used by the ClientThread. The ID of the thread passed to the HelperThread for further termination using this function. Used solely by ClientThread.

  • CleanupThread(...) - Closes main listen socket and some handles. Used by AcceptThread only.

  • AcceptThread(...) - Main working thread that serves all incoming connections.

  • ClientThread(...) - Serves all established client connections.

  • HelperThread(...) - If I'm not using _endthread(...), someone should close the threads handle after it is no longer alive. That function is assigned to the HelperThread.

The following abstract functions should be implemented if you derive your class from the CGenericServer:

  • IsComplete(...) - This function is very important to implement carefully. You have to determine whether the whole message is in the buffer or not based on the data you have when this function has been called. In my example of the HTTP server, the condition is double \r\n.

  • ParseRequest() - This is also a very important function. It will provide you with the data received from the client and must take response data from you. If you return a false, connection will be closed immediately, and the thread will be killed. Otherwise, it will remain opened, unless you assign the KeepAlive variable as 1. You will find basic HTTP implementation in my example.

  • GotConnection(...) - This will give you the IP address and port number of the connected client.

  • DataSent(...) - This should inform you each time data has been sent to the client, and gives you the number of bytes sent.

Additional notes

My HTTP server supports two of the most common HTTP errors:

  • 404 Resource not found
  • 504 Method not implemented

Each of these errors have corresponding html files. The names of those files are currently hard coded in HTTPServer.h. These files must be in the home directory of the server.

Also I've added several MIME types to the CHTTPServer class, so browsers can recognize those types. Of course there are many more types available. A simple CLog class has been used to log any errors that may occur. The log file will be placed in the Windows directory, and the filename is UMServer.log by default.

This is not a fully featured HTTP server and does not implement all the functionalities of the HTTP protocol, as this was not the main objective of this project.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Armenia Armenia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generalbuilding for 64-bit Pin
Dave Calkins29-Jul-21 9:17
Dave Calkins29-Jul-21 9:17 
QuestionSource is empty!! Pin
zcwtop4-Jan-13 2:10
zcwtop4-Jan-13 2:10 
AnswerRe: Source is empty!! Pin
lafaji26-Aug-14 12:50
lafaji26-Aug-14 12:50 
GeneralMy vote of 5 Pin
bladelyer3-Dec-12 16:44
bladelyer3-Dec-12 16:44 
Questionbuilding with VS2010 Pin
Dave Calkins24-Aug-11 9:09
Dave Calkins24-Aug-11 9:09 
AnswerRe: building with VS2010 Pin
airong19-Oct-11 17:16
airong19-Oct-11 17:16 
Generalthanks thanks http://www.codeplex.com/AudioAndShoutcast/Thread/View.aspx?ThreadId=45814 Pin
di~v~inci31-Jan-09 13:01
di~v~inci31-Jan-09 13:01 
Generalthank you! Pin
-=Seph=-12-Feb-08 23:35
-=Seph=-12-Feb-08 23:35 
GeneralIE vs Firefox Pin
João Paulo Figueira3-Sep-07 12:04
professionalJoão Paulo Figueira3-Sep-07 12:04 
QuestionDetermining media type by file extension Pin
Angus Comber6-May-07 8:31
Angus Comber6-May-07 8:31 
QuestionGET where need output of a cgi or exe Pin
Angus Comber5-May-07 6:44
Angus Comber5-May-07 6:44 
GeneralBug fix for url that contain %20 expression Pin
darkzangel24-Aug-05 13:52
darkzangel24-Aug-05 13:52 
GeneralProblem found with a slow http client Pin
jeffreycui@hotmail.com8-Oct-04 9:28
jeffreycui@hotmail.com8-Oct-04 9:28 
GeneralRe: Problem found with a slow http client Pin
jkubo16-Nov-04 2:01
jkubo16-Nov-04 2:01 
GeneralRe: Problem found with a slow http client Pin
jeffreycui@hotmail.com18-Nov-04 11:27
jeffreycui@hotmail.com18-Nov-04 11:27 
GeneralRe: Problem found with a slow http client Pin
jkubo23-Nov-04 3:55
jkubo23-Nov-04 3:55 
Hallo Jeffrey, there is maybe problem:

const char CONTENT_LENGTH[] = "\r\nContent-Length: ";
int nStart = szRequest.find( CONTENT_LENGTH, 0 );
if( nStart != -1 )
{
nStart += strlen( CONTENT_LENGTH );
int nEnd = szRequest.find( CR_LF, nStart );
string szContentLen = szRequest.substr( nStart, nEnd - nStart );
int nContentLen = atoi( szContentLen.c_str() );
if( szRequest.size() >= nHeaderEnd + 4 + nContentLen )
{
Ret = TRUE;
}
}
>>>>>>>else
>>>>>>>{
>>>>>>>Ret = TRUE;
>>>>>>>}

If content length property can't be found then isn't request complete...or my mistake? Bye, Jarek

PS: ...and missing defines for total rookies in HTTP (I am only rookie Big Grin | :-D ):

#define CR_LF "\r\n"
#define HEADER_END "\r\n\r\n"

PS1: It's better to use string::npos instead -1...said to me my colleague on code review Smile | :) It was shame.....Big Grin | :-D
GeneralGreat Work - Another Request Pin
alan9316-Jun-03 14:47
alan9316-Jun-03 14:47 
Generalinterested in further development and bug fixes Pin
BrankoL19-Aug-02 7:22
BrankoL19-Aug-02 7:22 
Generaljust a question Pin
Morozov Alexey19-Dec-01 17:38
Morozov Alexey19-Dec-01 17:38 
GeneralRe: just a question Pin
Rickard Andersson201-Nov-03 3:12
Rickard Andersson201-Nov-03 3:12 
GeneralIO Completion Ports Pin
Giles14-Aug-01 9:39
Giles14-Aug-01 9:39 
GeneralRe: IO Completion Ports Pin
20-Aug-01 7:33
suss20-Aug-01 7:33 
GeneralRe: IO Completion Ports Pin
9-Oct-01 12:19
suss9-Oct-01 12:19 
GeneralRe: IO Completion Ports Pin
User 98859-Oct-01 12:36
User 98859-Oct-01 12:36 
GeneralRe: IO Completion Ports Pin
3-Dec-01 22:34
suss3-Dec-01 22:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.