- Internetprogrammering 99/00 -

Konstruktion av server version-2 (senast ändrat 991021)

Exempel som hjälp för laboration 6.
Exemplet visar hur en enkel server i ett meddelandesystem kan konstrueras.
I nästa del av exemplifieringen av meddelandesystemt bygger vi också en  klient som kan utnyttja servern och dess kommandon, se Konstruktion av klient version-2.

Serverklass

Det här exemplet illustrerar en  server som kan hantera dom kommandon som beskrevs på exemplens startsida.

Implementationside

Avtolkningen av kommandon till servern är baserade på det så kallade designmönstret strategy (se tex design patterns hemsida, http://hillside.net/patterns/, för massor av intressanta referenser). Kortfattat kan man säga att beroende av första ordet på kommandoraden väljs olika objekt, dvs olika strategier, som sedan ansvarar för resten av kommandoavkodningen samt att se till att rätt metoder hos servern utförs och lämpligt svar till klienten ges.
Fördelarna med detta mönster är många. Bland annat blir det enkelt att lägga till nya kommandon senare. Vidare får vi en bra objektorienterad struktur på programmet.
För att göra detta förfarande enkelt initieras en klassvariabel, CommandDispatcher, som  instansieras till att vara en Hashtable (dvs en tabell där värden kan slås upp med givna nycklar). Varje kommandonamn blir en nyckel i tabellen och som värde vid respektive nyckel sätts en instans av någon av den abstrakta klassen Command:s subklasser.
Värdena initieras i ett statiskt block
static {
   // kod
}
Dvs ett block som utförs då aktuell klass laddas (vilket gör att vi, som här, på ett smidigt sätt bla kan initiera klassvariabler).

Förslag till förbättring (överkurs)

Klassen Command med subklasser är konstruerade som privata inre klasser till TestServerSocketVersion2 men kan med fördel konstrueras som publika klasser i egna filer. Orsaken att det är gjort som det är gjort här är att vi för enkelhets (och överskådlighets) skull vill hålla samman koden. Men i det generella fallet bör man överväga det alternativa sättet.
Ett annat alternativ som kan övervägas är om Command istället skall definieras som ett interface. Vilket skulle medföra att kommandoklasserna inte behöver hänga ihop i en klasshierarki.
Vi kan också överväga om inte ett interface skall ersätta  argument som är deklarerade som TestServerSocketVersion2. Ett sådant interface skulle på ett mer generellt sätt beskriva serverns API och därför skulle klasserna som innehåller sådana metoder enklare kunna användas i andra sammanhang (dvs inte bli så hårt bundna till klassen TestServerSocketVersion2).

Exempel Hashtable

Som exempel visar vi hur en enkel tabell med några instanser av subklasser till Command som värden kan skapas. Här initierar vi värdena direkt (dvs static-blocket är utelämnat).
Hashtable CommandDispatcher = new Hashtable();
CommandDispatcher.put("connect", new Connect());
CommandDispatcher.put("listIDs", new ListIDs());
CommandDispatcher.put("listUsernames", new ListUsernames());
CommandDispatcher.put("messageToID", new MessageToID());
Om vi sedan tex vill ha tag i objektet vid "nyckeln" listIDs, tilldela det till en variabel, och skicka meddelandet info() till denna variabel så kan koden se ut i stil med:
Command currentCommand;
currentCommand = (Command) CommandDispatcher.get("listIDs");
currentCommand.info();
Där kommandot get(...) "ber" en Hashtable om objektet vid aktuell nyckel, "castingen" (Command) behövs då vi vill använda ett meddelande vars metod finns i klassen Command. Orsaken till att "castingen" behövs är att i Hashtable är alla värden deklarerade som Object (dvs om vi inte "castar" kan vi bara använda meddelanden som finns i Object även om vi kan lägga in instanser av andra klasser).

Konstruera serversocket och lyssna efter klienter

Inga konstigheter utan vi gör ungefär som i version-1 av servern.
Eventuellt skulle man kunna överväga att använda trådar, eller lättviktsprocesser, men för att hålla komplexiteten nere väljer vi att inte göra detta i exemplet.
För detaljer se källkoden.

Test av servern

Starta servern som vanligt Javaprogram. Observera att vi kör på fast portnummer, 4447.
Går att testa via telnet.
Det går också att köra speciella klienter, se klient version-2 för detaljer om klienter.

Källkod till exemplet

I filen TestServerSocketVersion2.java hittar du koden för servern.

^ Upp till kursens hemsida.


Sidansvarig: <bjorne@nada.kth.se>
Senast ändrad 21 oktober 1999