SignalRPróbowałeś kiedyś napisać chat. Co ile sekund ma on wyciągać dane od serwera? Nie to z góry kiepski pomysł.

Lepszą techniką jest “long polling”. Otwieramy połączenie i utrzymujemy je otwarte zmuszając klienta (przeglądarkę) do czekania udając ,że dane połączenie rzeczywiście trwa długo.

Jeżeli połączenie jest zerwane wtedy połączenie jest otwierane ponownie po obu stronach(klient serwer). W przyszłość WebSockety  rozwiążą ten problem lepiej.

TofikW .NET nie ma silnej odpowiedzi na ten problem.

WCF średnio nadaje się do tworzenia tak zwanych topików (topic) i aplikacji typu chat. Połączenie musi istnieć i po stronie klienta i serwera. Czyli musi użyć połączenia WCF typu duplex. Jak jednak utrzymywać połączenie z klientem i je wznawiać. Strasznie dużo roboty.

Nawet miałem napisać coś takiego  na studiach ,ale wolałem wybrać MSMQ i ZeroC (alternatywa dla CORBA) do prezentacji różnych rozwiązań transportowych w .NET.

Zresztą wykładowcy nie podobało się to ,że wszystkie moje rozwiązania  są w magicznej technologii o jednej nazwie WCF.

.NET w sumie nie miał jakiś mocnej odpowiedzi na te problemy ,aż dotąd.

SignalR daje dwa programistyczne modele połączenia (hubs, persistent connections).  SignalR ma wbudowane następujące techniki transportowe.

  • WebSockets (wspierane przez niektóre przeglądarki)
  • Server Sent Events (ta technika wspiera notyfikację w stylu “push”. IE z tego nie korzysta)
  • Forever Frame  (technika wysłania skryptowych bloków do ukrytego IFrame)
  • Long polling (technika została objaśniona na początku wpisu)

SignalR wybiera najlepszy typ transportu, które są wspierane i przez klienta i serwera. (chociaż można wymusić określony transport).

Jeśli jesteś zainteresowany jak każdy z tych funkcji transportowych działa możesz podejrzeć je w  kodzie źródłowym.

Użycie SignalR, jeśli chodzi o klienta nie kończy się na stronie ASP.NET. Klientem może być aplikacja napisana w WPF, Silverlight, Windows Phone 8 oraz WinRT.

Istnieje biblioteka SignalR do IPhone https://github.com/DyKnow/SignalR-ObjC Na StackOverflow opinie są pozytywne.

Z Androidem jest trochę gorzej. Jeden programista postanowił napisać taką bibliotekę od zera. https://github.com/erizet/SignalA

Przykłady z SignalR są imponujące.

Pamiętam jak na studiach inżynierski ktoś do swojej pracy dyplomowej pisał grę w statyki i miał właśnie problem z odświeżaniem informacji dla różnych klientów. Nie dziwiło mnie to bo do rozwiązania problemu używała ASP.NET AJAX.

Ten prosty przykład poniżej uświadomił mi, że zapewne jego problem można byłoby  rozwiązać teraz  w kilka minut.

SignalR

Link do tutorialu objaśniającego krok po kroku ja napisać taką aplikację.

http://www.asp.net/signalr/overview/getting-started/tutorial-high-frequency-realtime-with-signalr.

Jak widać nowy stan obiektu jest w miarę szybko przekazywany do innego klienta przeglądarki.

ASP.NET SignalR Stock Ticker

Przykład z Stock Ticker. https://github.com/SignalR/SignalR-StockTicker

Jak widać klient szybko odbiera zmiany danych.

Jak bardzo SignalR jest proste w użyciu? Napiszmy szybko aplikację.

Szybka aplikacja SignalR

Utwórz pusty projekt web ASP.NET i do projektu używając NuGet dodaj następujące paczki

  • Microsoft ASP.Net SignalR JS
  • Microsoft ASP.Net SignalR SystemWeb

NuGet SignalR

Teraz musimy napisać kod po stronie klienta i serwera.

Do projektu dodaj następująca klasę.

public class LogHub : Hub
{
    public static bool NotStarted = true;
    public static readonly System.Timers.Timer _Timer = 
	new System.Timers.Timer();

    public LogHub()
    {
        if (NotStarted)
        {
            _Timer.Interval = 10000;
            _Timer.Elapsed += TimerElapsed;
            NotStarted = false;
            _Timer.Start();
        }
    }

    public void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        Clients.All.logMessage(string.Format
	("{0} - Działa nadal", DateTime.UtcNow));
    }

}

Widzimy ,że klasa dziedziczy po klasie “hub”. Co to jest “hub”.

A hub is a structure that facilitates simple communications to a collection of client systems that are listening for commands to execute. 

Co ta klasa będzie robić? Będzie ona wysłać co 10 sekund komunikat “Działa nadal” do wszystkich klientów.

Clients SignalR

Jesteśmy wstanie wysłać wiadomości do określonych klientów wedle życzenia. Warto też zaznaczyć ,że metoda “logMessage” jest składową dynamicznego obiektu i teorii ona nie istnieje..

Właściwości “All, Others, Caller” są tak naprawdę obiektami proxy i ich metody będą dostępne dla klienta, gdy zostaną one wywołane przez SignalR.

Poniżej znajduje się kod strony HTML. Widzimy tutaj referencje do skryptu jQuery i do skryptu signalR. Na samym końcu mamy także referencję do dynamicznego skryptu “/signalr/hubs”, który zostanie stworzony w trakcie kompilacji. Jak się zapewne domyślasz ten skrypt wystawia wszystkie metody usługi SignalR dla JavaScript tak aby mogły być one użyte w przeglądarce.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="Scripts/jquery-1.6.4.min.js"></script>
    <script src="Scripts/jquery.signalR-1.0.1.js"></script>
        <script src="/signalr/hubs"></script>

</head>
<body>
    <ul id="logUl">
        
    </ul>
    <script type="text/javascript">

        $(function () {

            var logger = $.connection.logHub;

            logger.client.logMessage = function (msg) {

                $("#logUl").append("<li>" + msg + "</li>");

            };

            $.connection.hub.start();

        });

</script>
</body>
</html>

Zanim uruchomisz ten przykład musisz jeszcze do pliku global.asax dodać ścieżkę mapowania hub-ów. Inaczej dynamiczne skrypty “/signalr/hubs” nie zostaną utworzone.

public class Global : System.Web.HttpApplication
{
    protected void Application_Start(object sender, EventArgs e)
    {
        RouteTable.Routes.MapHubs();
    }
}

Oto rezultat mojego działania.

Nadal działa SignalR

Zbyt prosty przykład? Oto tutorial jak napisać bardzo szybko aplikację chat.

Muszę przyznać ,ze SignalR wydaje się naprawdę potężnym narzędziem, zwłaszcza że możemy z niego skorzystać nie tylko w ASP.NET.

Jeśli planujesz napisać jakąś grę wymagającą dynamicznego odświeżania ekranu dla wielu klientów to SignalR jest dobrym początkiem.