This basically replicates the “Simple C# Web Server” that is done over at “David’s” Blog:
https://codehosting.net/blog/BlogEngine/post/Simple-C-Web-Server
I use pretty much the same code – I have given the code the once-over using Re-Sharper. Other than that, the only real difference is that this post actually tells you how to get started and how to demonstrate the thing – useful info for complete newbies, I think.
In Visual Studio create a new Console Application:
In Program.cs we update the code to include the WebServer class which initializes the HttpListener prefixes – these represent the collection of prefix(s) used to store Uniform Resource Identifier (URI) values for the HttpListener object.
The WebServer class also implements methods to run and stop the web service.
The main program thread creates an instance of the web server, and runs it as a background thread, and which is stopped whenever the user presses any key. The thread runs the while loop to continuously listen for http requests. Once it ‘hears’ the http request the responder method returns the html string it created, this is converted into bytes and then used to create the http response in the form of a stream object:
var rstr = _responderMethod(ctx.Request); var buf = Encoding.UTF8.GetBytes(rstr); ctx.Response.ContentLength64 = buf.Length; ctx.Response.OutputStream.Write(buf, 0, buf.Length);
Full code listing of Program.cs as follows:
using System; using System.Collections.Generic; using System.Net; using System.Text; using System.Threading; namespace WebServer { public class WebServer { private readonly HttpListener _listener = new HttpListener(); private readonly Func<HttpListenerRequest, string> _responderMethod; public WebServer(IReadOnlyCollection<string> prefixes, Func<HttpListenerRequest, string> method) { if (!HttpListener.IsSupported) { throw new NotSupportedException("Needs Windows XP SP2, Server 2003 or later."); } // URI prefixes are required eg: "http://localhost:8080/test/" if (prefixes == null || prefixes.Count == 0) { throw new ArgumentException("URI prefixes are required"); } if (method == null) { throw new ArgumentException("responder method required"); } foreach (var s in prefixes) { _listener.Prefixes.Add(s); } _responderMethod = method; _listener.Start(); } public WebServer(Func<HttpListenerRequest, string> method, params string[] prefixes) : this(prefixes, method) { } public void Run() { ThreadPool.QueueUserWorkItem(o => { Console.WriteLine("Webserver running..."); try { while (_listener.IsListening) { ThreadPool.QueueUserWorkItem(c => { var ctx = c as HttpListenerContext; try { if (ctx == null) { return; } var rstr = _responderMethod(ctx.Request); var buf = Encoding.UTF8.GetBytes(rstr); ctx.Response.ContentLength64 = buf.Length; ctx.Response.OutputStream.Write(buf, 0, buf.Length); } catch { // ignored } finally { // always close the stream if (ctx != null) { ctx.Response.OutputStream.Close(); } } }, _listener.GetContext()); } } catch (Exception ex) { // ignored } }); } public void Stop() { _listener.Stop(); _listener.Close(); } } internal class Program { public static string SendResponse(HttpListenerRequest request) { return string.Format("<HTML><BODY>My web page.<br>{0}</BODY></HTML>", DateTime.Now); } private static void Main(string[] args) { var ws = new WebServer(SendResponse, "http://localhost:8080/test/"); ws.Run(); Console.WriteLine("A simple webserver. Press a key to quit."); Console.ReadKey(); ws.Stop(); } } }
Before running the server I open up a web browser (Chrome in this case), and enter the example URI prefix we use in this program ie http://localhost:8080/test/.
As you can see the site cannot be reached as the server has not been started yet.
I then start running the web server console application:
The web browser content is updated with the newly created response stream as shown: