This project may help you to create a web server from scratch: MiniHttpd: an HTTP web server library using pure TCP/IP
But instead of dealing with many unnecessary details such as parsing headers, compression, authentication, ssl etc. I would use the built-in HttpListener class.
Here is a simplified(but working) multi-threaded WebServer
void CreateWebServer()
{
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://*:8080/");
listener.Start();
new Thread(
() =>
{
while (true)
{
HttpListenerContext ctx = listener.GetContext();
ThreadPool.QueueUserWorkItem((_) => ProcessRequest(ctx));
}
}
).Start();
}
void ProcessRequest(HttpListenerContext ctx)
{
string responseText = "Hello";
byte[] buf = Encoding.UTF8.GetBytes(responseText);
Console.WriteLine(ctx.Request.Url);
ctx.Response.ContentEncoding = Encoding.UTF8;
ctx.Response.ContentType = "text/html";
ctx.Response.ContentLength64 = buf.Length;
ctx.Response.OutputStream.Write(buf, 0, buf.Length);
ctx.Response.Close();
}
EDIT
I changed the server a little bit to make it host a RESTful WebService (MyService
). It returns the the result as Json. You can call it as http://localhost:8080/?method=Calc&i=5&j=4
(I omitted many error checks for simplicity)
public class MyService
{
public Result Calc(int i, int j)
{
return new Result() { Addition = i + j, Multiplication = i * j };
}
}
public class Result
{
public int Addition { set; get; }
public int Multiplication { set; get; }
}
void CreateWebServer()
{
MyService service = new MyService();
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://*:8080/");
listener.Start();
new Thread(
() =>
{
while (true)
{
HttpListenerContext ctx = listener.GetContext();
ThreadPool.QueueUserWorkItem((_) => ProcessRequest(ctx,service));
}
}
).Start();
}
void ProcessRequest(HttpListenerContext ctx,MyService service)
{
try
{
string responseText = Execute(ctx, service);
byte[] buf = Encoding.UTF8.GetBytes(responseText);
ctx.Response.ContentEncoding = Encoding.UTF8;
ctx.Response.ContentType = "application/json";
ctx.Response.ContentLength64 = buf.Length;
ctx.Response.OutputStream.Write(buf, 0, buf.Length);
}
catch
{
ctx.Response.StatusCode = (int) HttpStatusCode.NotFound;
}
ctx.Response.Close();
}
string Execute(HttpListenerContext ctx, MyService service)
{
System.Collections.Specialized.NameValueCollection nv = HttpUtility.ParseQueryString(ctx.Request.Url.Query);
MethodInfo mi = service.GetType().GetMethod(nv["method"]);
object[] parameters = mi.GetParameters()
.Select(pi => Convert.ChangeType(nv[pi.Name], pi.ParameterType))
.ToArray();
return JsonConvert.SerializeObject(mi.Invoke(service, parameters));
}