Fetstil Fetstil Kursiv Understrykning linje färgläggning tabellverk Punktlista Nummerlista Vänster Centrerat högerställt Utfyllt Länk Bild htmlmode
  • Forum & Blog
    • Forum - översikt
      • .Net
        • asp.net generellt
        • c#
        • vb.net
        • f#
        • silverlight
        • microsoft surface
        • visual studio .net
      • databaser
        • sql-server
        • databaser
        • access
        • mysql
      • mjukvara klient
        • datorer och komponenter
        • nätverk, lan/wan
        • operativsystem
        • programvaror
        • säkerhet, inställningar
        • windows server
        • allmänt
        • crystal reports
        • exchange/outlook
        • microsoft office
      • mjukvara server
        • active directory
        • biztalk
        • exchange
        • linux
        • sharepoint
        • webbservers
        • sql server
      • appar (win/mobil)
      • programspråk
        • c++
        • delphi
        • java
        • quick basic
        • visual basic
      • scripting
        • asp 3.0
        • flash actionscript
        • html css
        • javascript
        • php
        • regular expresssion
        • xml
      • spel och grafik
        • DirectX
        • Spel och grafik
      • ledning
        • Arkitektur
        • Systemutveckling
        • krav och test
        • projektledning
        • ledningsfrågor
      • vb-sektioner
        • activeX
        • windows api
        • elektronik
        • internet
        • komponenter
        • nätverk
        • operativsystem
      • övriga forum
        • arbete karriär
        • erbjuda uppdrag och tjänster
        • juridiska frågor
        • köp och sälj
        • matematik och fysik
        • intern information
        • skrivklåda
        • webb-operatörer
    • Posta inlägg i forumet
    • Chatta med andra
  • Konto
    • Medlemssida
    • Byta lösenord
    • Bli bonsumedlem
    • iMail
  • Material
    • Tips & tricks
    • Artiklar
    • Programarkiv
  • JOBB
  • Student
    • Studentlicenser
  • KONTAKT
    • Om pellesoft
    • Grundare
    • Kontakta oss
    • Annonsering
    • Partners
    • Felanmälan
  • Logga in

Hem / Artiklar / Titel på artikeln

.NET 3.0 en liten översikt - del 2

Postad 2006-11-22 av Simon Dahlbacka i sektionen ASP.NET, C#, Okategoriserat med 0 Kommentarer | Läst av: 5591, Betyg: 80%

Förord

Vi fortsätter att utforska .NET 3.0 frameworket med genom en fallstudie på en chatt applikation. I denna artikel koncentrerar vi oss på server sidan.
Innehåll
  » Vad behövs för en server
  » Host kod
  » Service provider
  » Service implementation
  » Meddela klienterna
  » Service konfiguration
  » Avslutningsvis
Relaterade artiklar
  » .NET 3.0 en liten översikt - del 1
  » .NET 3.0 en liten översikt - del 3
  » .NET 3.0 en liten översikt - del 4 (WPF)
  » .NET 3.0 en liten översikt - del 5 (WPF)
  » .NET 3.0 en liten översikt - del 6 (WPF) - sista delen
I del 1 av artikelserien började vi med vårt chatt system och vi defineierade WCF gränssnittet för vår chatt service. Nästa grej vi tittar på hur vi implementerar server funtionaliteten för chatten.


Vad behövs för en server

En WCF består av några olika delar. För det första, så behöver den ”hostas” någonstans, ett sätt är att låta IIS sköta detta, men i detta fall har jag valt att sköta det själv. Ingendera versionen är speciellt komplicerad.


Host kod

Vi dyker rakt in i koden...

using System;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace LemonDesign.ChatServer {
class ServerProgram {
static void Main(string[] args) {
ServiceHost host = new ServiceHost(ChatProvider.Instance,
new Uri("http://" + Dns.GetHostName() + ":81"),
new Uri("net.pipe://" + Dns.GetHostName()));
Console.WriteLine("Chat server starting ...");
foreach (ServiceEndpoint endpoint in host.Description.Endpoints) {
Console.WriteLine("Serving at address {0}:", endpoint.Address);
}
host.Open();
Console.WriteLine("Press enter to shut down ...");
Console.ReadLine();
host.Close();
}
}
}


Med WCF kommer ServiceHost klassen som gör det mesta av jobbet åt oss, det enda du behöver göra är att ge den klassen som implementerar service interfacet, dvs. vårt chatt interface, samt bas adress(er) där servicen skall göras tillgänglig.

För demonstrationens skull har jag valt att låta servicen publiceras både över http samt över named pipes (som är effektivare, men funkar enbart när klient och server finns på samma dator.)


Service provider

Först har vi tämligen ointressant boilerplate kod

using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Threading;

using LemonDesign.Chat.Contract;

namespace LemonDesign.ChatServer {

///
/// Helper class
///

internal class UserMessagePair {
public string User;
public string Message;

public UserMessagePair(string user, string message) {
User = user; Message = message;
}
}


Service implementation

Sedan kommer vi till den intressanta delen. Vår service klass implementerar vårt IChat interface, och med ServiceBehavior attributet indikerar vi att vår service är en singleton som kan accesseras av flera klienter samtidigt. (Vilket ju är rätt naturligt för en chatt applikation)

///
/// Implementation of the service interface
///

/// There will ever be only one instance of the server, but multiple clients are allowed concurrently.
[ServiceBehavior(Namespace="urn:LemonDesign:Chat", ConcurrencyMode=ConcurrencyMode.Multiple,
InstanceContextMode=InstanceContextMode.Single)]
public class ChatProvider : IChat {

private static readonly ChatProvider m_instance = new ChatProvider();
private static readonly object m_concurrencyLock = new object();
private Dictionary m_clients;

///
/// Service implementation singleton accessor
///

public static ChatProvider Instance {
get { return m_instance; }
}

private ChatProvider() {
m_clients = new Dictionary();
}

#region IChat Members
///
/// Called when a client connects.
///

/// the client username
public void Connect(string username) {
Console.WriteLine("{0} {1} connected ...", username, OperationContext.Current.SessionId);
lock (m_concurrencyLock) {
m_clients[OperationContext.Current] = username;
}
}

///
/// Called when a client disconnects.
///

public void Disconnect() {
Console.WriteLine("{0} disconnected ...", OperationContext.Current.SessionId);
lock (m_concurrencyLock) {
if (m_clients.ContainsKey(OperationContext.Current)) {
m_clients.Remove(OperationContext.Current);
}
}
}


Meddela klienterna

Även fast vi tillåter många klienter samtidigt, så tillåts inte reentranta anrop, därför måste vi putta iväg den delen till en annan tråd, så att anropet till Say metoden får köras klart.

///
/// Called when client says a message
///

/// the message
public void Say(string message) {
Console.WriteLine("{0} said {1}", OperationContext.Current.SessionId, message);
// check for obscenity
if (message.Contains("fuck") || message.Contains("shit")) {
throw new FaultException(new ObscenityException("You cannot use such obscenities in this chat..."));
}
// this code sucks, but oh well ...
string user = "alien";
foreach (OperationContext ctx in m_clients.Keys) {
if (ctx.SessionId == OperationContext.Current.SessionId) {
user = m_clients[ctx];
}
}
// need to hand this off to another thread, otherwise we'll get a deadlock...
ThreadPool.QueueUserWorkItem(TellClients,
new UserMessagePair(user, message));
}


///
/// Called from a threadpool thread, notifies all clients about a new message
///

/// the message
private void TellClients(object state) {
UserMessagePair pair = state as UserMessagePair;
lock (m_concurrencyLock) {
foreach (OperationContext clientCtx in m_clients.Keys) {
IChatEvents callbackInterface = clientCtx.GetCallbackChannel();
try {
if (callbackInterface != null) {
callbackInterface.MessageReceived(new Message(pair.User, pair.Message));
}

} catch (Exception e) {
Console.WriteLine("Err: something bad happened {0}", e.Message);
}
}
}
}

#endregion
}
}




Service konfiguration

Det var själva kodbiten av det hela, sen är det bara en liten bit kvar, nämligen konfigureringen av servicen. Detta går naturligtvis även att göra inne i koden, men för att så att säga hålla dörrarna öppna är det bra att köra det från konfigurationsfilen.

Därför pillar vi in följande i app.config






contract="LemonDesign.Chat.Contract.IChat"/>
contract="LemonDesign.Chat.Contract.IChat"/>






Contract attributet här är alltså satt till det kvalificerade namnet på vårt service gränssnitt. Name attributet anger namnet på service klassen som implementerar gränssittet.

Som ni ser kan en service ha flera så kallade endpoints, det vill säga adresser/protokoll som kan användas för att ta kontakt med servicen.


Avslutningsvis

Nu har vi alltså skapat ett service gränssnitt (i del 1), och skapat en service som implementerar detta gränssnitt. Då återstår bara att skapa en klient så att vi kan testa huruvida det funkar. Detta är då ämnet för nästa artikel.

Återigen, frågor och kommentarer mottages tacksamt.
Upp

0 Kommentarer

Skriv en kommentar på artikeln

Ditt betyg på artikeln



Kommentar:





Nyligen

  • 09:09 Vill du köpa medicinska tester?
  • 12:47 Vem beviljar assistansen – kommune
  • 14:17 Någon med erfarenhet av hemstädnin
  • 14:14 Bör man använda sig av en båtförme
  • 14:12 Finns det någon intressant hundblo
  • 14:25 Tips på verktyg för att skapa QR-k
  • 14:23 Tips på verktyg för att skapa QR-k
  • 20:52 Fungerer innskuddsbonuser egentlig

Sidor

  • Hem
  • Bli bonusmedlem
  • Läs artiklar
  • Chatta med andra
  • Sök och erbjud jobb
  • Kontakta oss
  • Studentlicenser
  • Skriv en artikel

Statistik

Antal besökare:
Antal medlemmar:
Antal inlägg:
Online:
På chatten:
4 569 153
27 952
271 704
1 200
0

Kontakta oss

Frågor runt konsultation, rådgivning, uppdrag, rekrytering, annonsering och övriga ärenden. Ring: 0730-88 22 24 | pelle@pellesoft.se

© 1986-2013 PelleSoft AB. Last Build 4.1.7169.18070 (2019-08-18 10:02:21) 4.0.30319.42000
  • Om
  • Kontakta
  • Regler
  • Cookies