WCF – dobieramy się do danych na serwerze

WCF – Windows Communication Foundation, bo o tym będzie mowa to, to framework do budowania aplikacji zorientowanych na serwisy (service-oriented applications). Przy jego pomocy jest możliwe przesyłanie informacji od jednego endpointa serwisu do innego endpointa. Przykładowo może to być przesyłanie danych pomiędzy serwerem (gdzie będziemy mieć zaimplementowane zbieranie danych z urządzeń) a klientem, który będzie dane pobierał z serwera i prezentował je w formie graficznej.

Serwer WCF
Klient WCF
Jak to działa? Pokażę na przykładzie rozwiązania składającego się z aplikacji serwerowej i aplikacji klienckiej.
Aplikacja serwerowa będzie nasłuchiwać na odpowiednim porcie i udostępniać pewne usługi a aplikacja kliencka będzie łączyć się do aplikacji serwerowej w celu wykonania danej usługi (np. pobrania danych).

wcf1Do tego celu wykorzystam VS2015 Community Edition. Zakładamy projekt o nazwie WCF (wybierając typ projektu „Console Application”). Następnie tworzymy w projekcie (w tym celu klikamy na „solution” w „solution explorer”) kolejny projekt konsolowy – tym razem nazywając go „WCF_Klient”.

Kolejnym krokiem będzie zmiana nazwy utworzonego projektu WCF na WCF_Server (klikamy w drzewie „Solution explorer” na nazwie „WCF” i wybierając „Rename” zmieniamy nazwę projektu na „WCF_Server”). Dodatkowo wybieramy „Properties” i zmieniamy „Assembly name” i „Default namespace” na WCF_Server.

wcf2W ten sposób w naszej solucji mamy dwa projekty konsolowe – jeden, który będzie serwerem (WCF_Server) i drugi, który będzie klientem (WCF_Klient).

W projekcie klienta (WCF_Klient) dodajemy referencję do projektu serwera (tak jak na załączonym obrazku);
wcf3

Serwer WCF

przejdź do „Klient WCF”
W projekcie serwera musimy dodać referencję do „System.ServiceModel” co przedstawia załączony obrazek:
wcf4
No i to tyle z „ustawień”, które musieliśmy poczynić by móc zająć się właściwym programem.

W programie serwera tworzymy interfejs IMessage, który będzie wykorzystywany do komunikacji (dodajemy przestrzeń nazw „System.ServiceModel”). Jak widać w ty, interfejsie będziemy mieć cztery metody (usługi), które zwracać będą odpowiednie informacje w postacji stringów. To co zwrócą będzie w implementacji interfejsu czyli klasie Message.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.ServiceModel;

namespace WCF_Server
{
    [ServiceContract]
    public interface IMessage
    {
        [OperationContract]
        string MsgHello();

        [OperationContract]
        string MsgGoodbye();

        [OperationContract]
        string MsgNow();

        [OperationContract]
        string MsgValue();
    }
}

Tworzymy klasę „Message”, która zawierać będzie implementację interfejsu „IMessage”. Widać tutaj co będą zwracać poszczególne metody. Ostatnia metoda MsgValue będzie zwracać nazwę miasta, która będzie się cyklicznie zmieniać co każdy interwał timera (widać to w kodzie programu w klasie „Program”).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WCF_Server
{
    class Message : IMessage
    {
        public string MsgGoodbye()
        {
            return "Good bye!";
        }

        public string MsgHello()
        {
            return "Hello World!";
        }

        public string MsgNow()
        {
            return DateTime.Now.ToString();
        }

        public string MsgValue()
        {
            return WCF_Server.Program.currentCity;
        }
    }
}

Klasa „Program” serwera prezentować będzie się następująco:

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

using System.Timers;

namespace WCF_Server
{
    class Program
    {
        public static string currentCity;
        static string[] Cities = new string[] { "Kraków", "Warszawa", "Poznań", "Wrocław", "Szczecin", "Gdańsk" };
        static int i = 0;
        
        static void Main(string[] args)
        {
            Timer tmr = new Timer();
            tmr.Interval = 5000;
            tmr.Elapsed += Tmr_Elapsed;
            tmr.Enabled = true;


            Uri address = new Uri("https://localhost:2222/");

            using (ServiceHost host = new ServiceHost(typeof(Message), address))
            {                
                host.AddServiceEndpoint(typeof(IMessage), new BasicHttpBinding(), address);

                try
                {
                    host.Open();
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.BackgroundColor = ConsoleColor.White;

                    Console.WriteLine("Serwer WCF uruchomiony [{0}] ...", DateTime.Now.ToString());
                    Console.ResetColor();

                    Console.ReadLine();                    
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }

        private static void Tmr_Elapsed(object sender, ElapsedEventArgs e)
        {
            currentCity = Cities[i];
            Console.SetCursorPosition(1, 3);
            Console.WriteLine("                                       ");
            Console.SetCursorPosition(1, 3);
            Console.WriteLine("-->{0}",currentCity);
            if (i < Cities.Length - 1)
            {
                i++;
            } else
            {
                i = 0;
            }
        }
    }
}

Wytłumaczenia wymaga tu kilka miejsc, które są kluczowe dla całego rozwiązania. Na początek definiujemy adres, na którym będzie pracować nasz serwer. Nie ma znaczenia numer portu ale ważne by nie był zajęty przez inny program.

Uri address = new Uri("https://localhost:2222/");

Definiowanie hosta, który będzie naszym serwerem. Wykorzystywać będzie ustawiony wcześniej adres oraz klasę Message (usługi)

ServiceHost host = new ServiceHost(typeof(Message), address)

Następnie tworzymy endpoint, z którym będzie komunikował się klient.

host.AddServiceEndpoint(typeof(IMessage), new BasicHttpBinding(), address);

Jeszcze tylko otwieramy host i to właściwie już pozwala nam na uruchomienie serwera.

host.Open();

Klient WCF

przejdź do „Serwer WCF”

Autor: gervee

Pełnoetatowy ojciec małej gromadki, programista(?), "amator" fotograf, "dłubacz" lubiący DIY, miłośnik chmielonego napitku. "Żartowniś" bez poczucia humoru ;).

Dodaj komentarz