Hur fungerar HttpListener i .NET Framework 2.0?

En av nyheterna som finns i .NET Framework 2.0 är klassen HttpListener i namnrymden System.Net. HttpListener kan vi tänka vara en liten bantad version av en webbserver som kan ta emot och svara på anrop över http utan att ha Internet Information Server installerad på datorn. Dock så krävs vissa funktioner i operativsystemet, vilket gör att HttpListener enbart fungerar på Windows XP med Service Pack 2 eller senare samt Windows Server 2003. Så hur fungerar då detta, jag brukar tycka att det är lättast att demonstrera med hjälp av kod och i det här fallet så har jag valt att implementera mitt projekt i Visual Studio 2005 Express och med hjälp av programmeringsspråket C#. Börja med att skapa en konsol-applikation som får agera värdapplikation för vår HttpListener. Lägg också genvägen till namnrymden System.Net.

using System.Net;

Vi kan snabbt ta reda på om HttpListener stöds av operativsystemet genom att testa en egenskap på HttpListener klassen som heter IsSupported. Genom att inkapsla vår logik i följande villkorssats slipper vi eventuella PlatformNotSupportedException fel som kommer att uppstå om applikationer försöker att exekveras på någon icke supporterad plattform:

if( HttpListener.IsSupported()
{
   // Resten av koden lägger vi här
}

Mitt HttpListener objekt definerar jag som ett statiskt objekt i klassen och döper till ourListener enligt nedanstående:

private static HttpListener ourLister = null;

För att få lite deterministik i hanteringen av vårt HttpListener objekt så kapslar jag in instansieringen av objektet med hjälp av nyckelordet Using.

using (ourListener = new HttpListener())
{
   // Och här använder vi ourListener
}

För att tala om för HttpListener vad som den ska lyssna efter så lägger vi till en uppsättning strängar som prefix, i det här fallet väljer jag att enbart lägga till ”https://localhost:8080/ourListener/” genom följande kod:

string prefix = ”https://localhost:8080/ourListenerPrefix/”;
ourListener.Prefixes.Add(prefix);

Sedan talar vi om för HttpListener att börja lyssna på den prefix som vi har specificerat.

ourListener.Start();

Nu har vi några möjligheter att välja hur vi vill att vår HttpListener ska ta emot anrop på det prefix som tidigare specificerats, antigen synkront eller asynkront. I det här första exemplet så väljer vi att lyssna synkront, vilket innebär att den metod som vi anropar kommer att vänta på att ett anrop till vårt prefix har skett och då returnera svaret tillbaka till vår metod. Jag kommer senare ta upp det asynkrona tillvägagångssättet. GetContext metoden som vi ska anropa returnerar ett context-objekt som kommer att innehålla både det request-objekt som skickas över http-protokollet och som vi sedan kan avända oss av, samt det response-objekt som vi också kan skriva till för att svara på anropet som kommit in till vår HttpListener.

HttpListenerContext context = ourListener.GetContext();

Vad vi sedan gör med vårt context-objekt är att läsa av response-objektet, skriva till det sistnämnda en HTML-formaterad sträng som innehåller de element som vi vill visa som svar till anropande klient. Det kan göras med följande kod:

HttpListenerResponse response = context.Response;

string responseString = "The time is currently " + DateTime.Now.ToString() + "";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;

System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);

response.Close();

Console.WriteLine(”Listening done...”);
Console.ReadLine();

Det är det som behövs för att vår kod ska kunna exekvera och fungera som vi förväntar oss, prova genom att starta applikationen, observera att applikationen kommer att stanna upp vid vårt synkrona anrop, det är då det är dags att öppna en webbläsare och ”surfa” till det prefix som vi har angett. Ange alltså adressen ”https://localhost:8080/ourListenerPrefix/”, om allt är som det ska så borde du få tillbaka en kort sträng med dagens datum och det aktuella tidsslaget, din applikation borde också avslutas eftersom det synkrona anropet är genomfört och HttpListener är dektiverad och avslutad. Hela koden ser ut som följande:

using System;
using System.Net;
namespace Lindfors.Johan.BlogPosts.HttpListenerDemo {
   class Program {
      private static HttpListener ourListener = null;
     
      static void Main(string[] args) {
         if (HttpListener.IsSupported) {
            using (ourListener = new HttpListener()) {
               string prefix = https://localhost:8080/ourListenerPrefix/";

               ourListener.Prefixes.Add(prefix);
               ourListener.Start();

               HttpListenerContext context = ourListener.GetContext();

               HttpListenerResponse response = context.Response;

               string responseString = "The time is currently " + DateTime.Now.ToString() + "";
               byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
               response.ContentLength64 = buffer.Length;

               System.IO.Stream output = response.OutputStream;
               output.Write(buffer, 0, buffer.Length);

               response.Close();

               Console.WriteLine(”Listening done...”);
               Console.ReadLine();
            }
         }
      }
   }
}