Environment: C#, .Net
SUMMARY
This article explains how to write a simple web server application using C#. Though it can be developed in any .net-supported language, I chose C# for this example. The code is compiled using beta2. Microsoft (R) Visual C# Compiler Version 7.00.9254 [CLR version v1.0.2914]. It can be used with Beta1 with some minor modifications. This application can co-exist with IIS or any web server, the key is to choose any free port. I assume that the user has some basic understanding of .net and C# or VB.Net. This Web server just returns html formatted files and also supports images. It does not load the embedded image or support any kind of scripting. I have developed a console-based application for simplicity.
First, we will define the root folder for our web server. Eg: C:\MyPersonalwebServer, and will create a Data directory underneath, our root directory Eg: C:\MyPersonalwebServer\Data. We will Create three files under the data directory i.e.
- Mimes.Dat
- Vdirs.Dat
- Default.Dat
Mime.Dat will have the mime type supported by our web server. The format will be
E.g.
.html; text/html
.htm; text/html
.bmp; image/bmp
VDirs.Dat will have the virtual directory Information. The format will be
E.g.
/; C:\myWebServerRoot/
test/; C:\myWebServerRoot\Imtiaz\
Default.Dat will have the virtual directory Information.
E.g.
default.html
default.htm
Index.html
Index.htm;
We will store all the information in plain text files for simplicity, we can use XML, registry, or even hard code it. Before proceeding to our code let us first look at the header information that the browser will pass while requesting our website
Let's say we request for test.html we type http://localhost:5050/test.html
(Remember to include the port in the URL), here is what the web server gets.
GET /test.html HTTP/1.1
- Accept: image/gif, image/x-bitmap, image/jpeg, image/jpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*
- Accept-Language: en-usAccept-Encoding: gzip, deflate
- User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; .NET CLR 1.0.2914)
- Host: localhost:5050Connection: Keep-Alive
Let us dive into the code
// MyWebServer Written by Imtiaz Alam
namespace Imtiaz
{
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
class MyWebServer
{
private TcpListener myListener;
private int port = 5050; // Select any free port you wish
// The constructor which makes the TcpListener start listening on the given port.
// It also calls a Thread on the method StartListen().
public MyWebServer()
{
try
{
// Start listening on the given port
myListener = new TcpListener(port);
myListener.Start();
Console.WriteLine("Web Server Running... Press ^C to Stop...");
// Start the thread which calls the method 'StartListen'
Thread th = new Thread(new ThreadStart(StartListen));
th.Start();
}
catch (Exception e)
{
Console.WriteLine("An Exception Occurred while Listening: " + e.ToString());
}
}
// Additional methods and properties can be added here
}
}
We defined the namespace, included the references required in our application, and initialized the port in the constructor, started the listener created a new thread, and called the startlisten function.
Now let us assume that the user does not supply the file name, in that case, we have to identify the default filename and send it to the browser, as in IIS we define the default document under the documents tab.
We have already stored the default file name in the default.dat and stored it in the data directory. The GetTheDefaultFileName function takes the directory path as input, opens the default.dat file looks for the file in the directory provided, and returns the file name or blank depending on the situation.
public string GetTheDefaultFileName(string sLocalDirectory)
{
StreamReader sr;
string sLine = "";
try
{
// Open the default.dat to find out the list
// of default file
sr = new StreamReader("data\\Default.Dat");
while ((sLine = sr.ReadLine()) != null)
{
// Look for the default file in the web server root folder
if (File.Exists(Path.Combine(sLocalDirectory, sLine)))
break;
}
}
catch (Exception e)
{
Console.WriteLine("An Exception Occurred: " + e.ToString());
}
if (File.Exists(Path.Combine(sLocalDirectory, sLine)))
return sLine;
else
return "";
}
We also need to resolve the virtual directory to the actual physical directory as we do in IIS. We have already stored the mapping between the Actual and Virtual directories in Vdir.Dat. Remember in all the cases the file format is very important.
public string GetLocalPath(string sMyWebServerRoot, string sDirName)
{
StreamReader sr;
string sLine = "";
string sVirtualDir = "";
string sRealDir = "";
int iStartPos = 0;
// Remove extra spaces
sDirName = sDirName.Trim();
// Convert to lowercase
sMyWebServerRoot = sMyWebServerRoot.ToLower();
sDirName = sDirName.ToLower();
try
{
// Open the Vdirs.dat to find out the list virtual directories
sr = new StreamReader("data\\VDirs.Dat");
while ((sLine = sr.ReadLine()) != null)
{
// Remove extra spaces
sLine = sLine.Trim();
if (sLine.Length > 0)
{
// Find the separator
iStartPos = sLine.IndexOf(";");
// Convert to lowercase
sLine = sLine.ToLower();
sVirtualDir = sLine.Substring(0, iStartPos);
sRealDir = sLine.Substring(iStartPos + 1);
if (sVirtualDir == sDirName)
{
break;
}
}
}
}
catch (Exception e)
{
Console.WriteLine("An Exception Occurred: " + e.ToString());
}
if (sVirtualDir == sDirName)
return sRealDir;
else
return "";
}
We also need to identify the Mime type, using the file extension supplied by the user.
public string GetMimeType(string sRequestedFile)
{
StreamReader sr;
string sLine = "";
string sMimeType = "";
string sFileExt = "";
string sMimeExt = "";
// Convert to lowercase
sRequestedFile = sRequestedFile.ToLower();
int iStartPos = sRequestedFile.IndexOf(".");
sFileExt = sRequestedFile.Substring(iStartPos);
try
{
// Open the Mime.Dat to find out the list of MIME types
sr = new StreamReader("data\\Mime.Dat");
while ((sLine = sr.ReadLine()) != null)
{
sLine = sLine.Trim();
if (sLine.Length > 0)
{
// Find the separator
iStartPos = sLine.IndexOf(";");
// Convert to lowercase
sLine = sLine.ToLower();
sMimeExt = sLine.Substring(0, iStartPos);
sMimeType = sLine.Substring(iStartPos + 1);
if (sMimeExt == sFileExt)
{
break;
}
}
}
}
catch (Exception e)
{
Console.WriteLine("An Exception Occurred: " + e.ToString());
}
if (sMimeExt == sFileExt)
return sMimeType;
else
return "";
}
Now we will write the function, to build and send header information to the browser (client)




DevlearnerPosted May 17, 2021, 1:01 PM
That's a WOW. But how would one make a real web domain instead of the localhost...?
David PopePosted Sep 25, 2012, 12:50 PM
I very much appreciate this starting point! thank you for your post, I have been looking for a starting point to build my own custom web server and this will get me started right away, thanks again!
johnPosted Sep 12, 2011, 12:54 AM
Unhandled Exception: System.MissingMethodException: Method not found: 'Void Syst em.Threading.ThreadStart..ctor(System.Object, UIntPtr)'. at Imtiaz.MyWebServer..ctor() at Imtiaz.MyWebServer.Main()
mudd mazaniPosted Mar 31, 2011, 3:33 AM
how to create simple web server in c.. coding in linux
Katherine MossPosted Sep 6, 2010, 2:54 AM
Hi, I thought that I'd make a suggestion for you to include how to get the server to support ASP.net or say something about SSL/TLS support. That'd be really cool!
HarunPosted Aug 30, 2008, 8:43 AM
hello. how can we use port 80 on windows xp.