Kategoriarkiv: Programmering

Diverse programmeringsrelaterede artikler

Geo IP redirigering

GeoLite City er et praktisk lille Open Source-værktøj fra firmaet MaxMind, som kan være til stor hjælp ved IP redirigering. Applikationen består i al sin enkelthed af en database-fil, samt en række C# klasser, som bruges til at tilgå databasen. Databasen kan bruges til at finde oplysninger om bl.a. land, landekode, region, by, postnummer, længde- og breddegrader og meget andet for en given IP-adresse.

Det Open Source API fra MaxMind som vi har anvendt består af seks C# klasser, hvoraf kun to skal instantieres for at benytte applikationen til fulde (der er API til yderligere programmeringssprog også, se forrige link). Det drejer sig om klasserne: LookupService og Location.

LookupService instantieres med en sti til databasen, samt (optionelt) en int, der fortæller om databasen skal læses direkte fra filen, eller gemmes i en buffer. Som standard læses der direkte fra filen, men i hastighedskritiske sammenhænge, kunne man muligvis ønske at cache databasen. Dernæst bruges LookupService objektet til at instantiere Location.

Location instantieres ved at kalde getLocation() på LookupService med den ønskede IP-adresse som parameter. Når det er gjort, er man klar til at udnytte de mange muligheder GeoLite City tilbyder. Dette gøres i første omgang ved at tilgå de public attributter der ligger i Location.

Dette eksempel udskriver land og breddegrad for IP-adressen, 208.77.188.166:
Bemærk at der kastes en exception hvis IP’en ikke findes, og koden bør derfor sættes i en try-catch blok.

LookupService ls = new LookupService(@"C:\...\...\GeoLiteCity.dat", GEOIP_STANDARD);
Location l = ls.getLocation("208.77.188.166");
Console.WriteLine("Land: " + l.countryName);
Console.WriteLine("Breddegrad: " + l.longitude.ToString());

Oplysninger om land ville i praksis f.eks. kunne bruges til, at redirigere en hjemmesidebruger hen til en version af siden i det pågældende lands sprog.

Man kunne også forestille sig, at en hjemmeside ønskede at vise mindre ressourcekrævende udgaver af siden til langsomme forbindelser. Her ville man også kunne benytte sig af GeoLite City. I dette tilfælde kunne koden se nogenlunde sådan her ud:
Bemærk at man her benytter LookupService og ikke Location.

int i = ls.getID("208.77.188.166");
if (i == LookupService.GEOIP_UNKNOWN_SPEED)
{
   Response.Redirect("http://example.net/standard.asp");
}
else if (i == LookupService.GEOIP_CABLEDSL_SPEED)
{
   Response.Redirect("http://example.net/fast.asp");
}
else if(i == LookupService.GEOIP_DIALUP_SPEED)
{
   Response.Redirect("http://example.net/slow.asp");
}

Her er et eksempel på en lille webapplikation, der oplyser land, by og koordinater for angivne IP adresser. Eksemplet vælger som standard www.hinnerup.net serverens globale IP. Der kan indtastes såvel IPv4 som IPv6 adresser i IP-adressefeltet.

GeoLite City kan hentes her og opdateres en gang om måneden.

O3D - 3D i browsere

3D grafik er sjovt. Og med O3D fra Google kan vi nu også få fuldt
hardware understøttet cross browser 3D grafik i browserne. Dette kan
give bedre muligheder for web spiludvikling naturligvis, men også
datavisualisering, 3D grafikere, legetøjsfirmaer der vil fange
interessen hos unge og hjemmesider, der bare gerne vil have et
ekstra pift kan nyde godt af dette.

For at anvende O3D skal der installeres en letvægts-plugin til din browser (lavet af Google naturligvis).
Derudover er selve O3D API’et er skrevet til Javascript, så webdevelopere behøver ikke lære et
nyt sprog for at bruge størstedelen af funktionaliteten. Undtagelsen
er shaders, der skrives i O3D’s eget shadersprog.

Endnu en fordel ved O3D er at det er cross browser og cross platform
kompatibelt. Således er både IE, Firefox, Safari og Chrome
understøttet i Windows, Linux og Mac OS X.

3D menu

Til at demonstrere mulighederne ved O3D har jeg lavet en lille
3D menu.

3D menuen er inspiret af 3D desktoppe som Compiz til Linux, hvor
brugerens forskellige desktoppe ligger på siden af en kube og der
skiftes mellem dem ved at vende kuben.

I eksemplet fungerer kubens sider som links og kan drejes for at
skifte link. Måden brugeren drejer kuben på er ved at trykke på
knapperne ovenfor eller bruge A eller S tasterne. Desuden kan man
zoome på W og S.

Muligheder demonstreret

I eksemplet demonstreres følgende:

  • Da O3D skrives i Javascript betyder det at det er nemt for
    webudviklere at foretage interaktioner mellem en given hjemmeside og
    3D miljøet. I eksemplet er dette demonstreret ved knapperne for
    oven, der er indsat som almindeligt HTML markup, og hvordan disse får kameraet til at
    svinge rundt om klodsen.
  • Dette demonstrerer en anden mulighed i O3D, nemlig at brugerne
    kan bevæge sig rundt i scenen.
  • Direkte interaktion med 3D miljøet er også en mulighed. I
    eksemplet illusteres dette ved at brugeren kan klikke på en figur i
    miljøet og blive dirigeret til en ny side.

O3D giver dog mulighed for langt mere end bare illustreret i dette ene
eksempel. De individuelle figure i scenen kan også bevæge sig, der kan
lægges texture på figurene, scener fra Maya og 3D Studio Max kan
importeres og der er understøttelse for shaders.

Flere eksempler og færdige programmer kan findes på
code.google.com

Udvidelses- og klassemetoder i C#

Jeg havde brug for at forklare forskellen på extension methods og almindelige klassemetoder idag, og det forbavsede mig i anledningen hvor længe siden det egentligt er jeg har brugt det selv i .NET sprog. Jeg bruger nemlig tit og ofte den “tilsvarende” mekanisme i JavaScript (f.eks. prototype nøgleordet).

Her er et eksempel på hvordan man kunne tælle alle ord i en streng ved brug af en almindelig klassemetode:

TestProgram.cs:

using System;
using System.Text;

namespace TestApplication
{
  public class Utilities 
  {
    public static int CountWords(String str)
    {
      return str.Split(new char[] { ' ', '.', '?' },
        StringSplitOptions.RemoveEmptyEntries).Length;
    }
  }

  class TestProgram
  {
    static void Main(string[] args)
    {
      String test = "Hello world, how are you doing?";

      Console.WriteLine(test);
      Console.WriteLine(Utilities.CountWords(test) + " words found.");
      Console.WriteLine("Press any key to quit.");
      Console.ReadKey();
    }
  }
}

Kørselsresultat:

Hello world, how are you doing?
6 words was found in the string.
Press any key to quit.

Metoden CountWords er her kun tilgængelig fra klassen Utilities. Men metoden er jo egentlig ret generel for alle instanser af String klassen, og det kunne nemt tænkes at den specielle funktion skal kaldes i fremtidige applikationer jeg laver, eller blot i andre klasser i samme applikation. Dertil kan man anvende extension methods til udvide de metoder der er tilgængelige i eksisterende klasser.

Extension methods, eller udvidelsesmetoder, implementeres ved at angive statiske metoder i en public static klasse. De klasser man har oprettet der indeholder udvidelsesmetoder skal så blot være i scopet der hvor man ønsker at anvende udvidelsesmetoderne. Dette sikres ved at benytte “using” direktivet for det namespace man har placeret klasserne for udvidelsesmetoderne i. Den første parameter i en udvidelsesmetode specificerer altid hviklen type (klasse) der udvides, og denne parameter skal altid indledes med en this modifikator, da det er denne modifikator sammen med static der får compileren til at genkende metoden som en udvidelsesmetode.   

Her et eksempel hvor Strings klassen får tilføjet en CountWords udvidelsesmetode:

MyExtensions.cs:

using System;
using System.Text;

namespace ExtensionMethods
{
  public static class MyExtensions
  {
    public static int CountWords(this String str)
    {
      return str.Split(new char[] { ' ', '.', '?' },
        StringSplitOptions.RemoveEmptyEntries).Length;
    }
  }
}

Den overstående klasse i namespacet ExtensionMethods udvider nu String klassen med metoden CountWords. Namespace navnet er ikke så vigtigt, det kan være hvad som helst faktisk. Udvidelsen af String klassen sker ved at this er angivet foran første parameter i CountWords metoden. Typen der udvides er String. Vi kan gøre brug af denne udvidelse ved at skrive “using ExtensionMethods;” i vores fremtidige applikationer, for eksempel:

TestProgram.cs:

using System;
using System.Text;
using MyExtensions;

namespace TestApplication
{
  class TestProgram
  {
    static void Main(string[] args)
    {
      String test = "Hello world, how are you doing?";

      Console.WriteLine(test);
      Console.WriteLine(test.CountWords() + " words found.");
      Console.WriteLine("Press any key to quit.");
      Console.ReadKey();
    }
  }
}

Kørselsresultat:

Hello world, how are you doing?
6 words was found in the string.
Press any key to quit.

Det er vigtigt at understrege at udvidelsen ikke finder sted på selve String klassen, men på instanser af String klassen. Helt konkret er det instansen str der modtages i selve CountWords metoden. Dette bevirker at man ikke kan lave klasse udvidelsesmetoder såsom “String.MyClassExtensionMethod” og tilsvarende. Ligeledes er adgangsniveauet for udvidelsesmetoder det samme som når man har med en given instans af en klasse at gøre. Man har således ikke adgang til protected og private metoder og egenskaber/variable på en klasse man udvider.

Microsoft Visual Studio’s Intellisense understøtter extension methods:

Der er lige et par huskeregler man bør have for øje:

  • Husk at udvidelsesmetoder kræver at der er anvendt et “using” direktiv.
  • Husk dermed at enten kildefilen eller DLL’en til ønskede udvidelsesmetoder er tilføjet projektet.
  • Endvidere skal man huske at eksisterende metoder med samme navn og signatur altid vinder over udvidelsesmetoder.
  • Tag ikke udvidelsesmetoder for givet. Anvend system metoder hvor muligt, og indfør kun udvidelsesmetoder under nøje overvejelser.

Se denne MSDN artikel, som mit eksempel herover er inspireret udfra, for flere uddybende eksempler.