poniedziałek, 15 grudnia 2014

[C#|Visual Studio] ASP .NET SignalR: Wprowadzenie

ASP .NET SignalR to genialny framework rozwiązujący problem notyfikacji serwerowych i komunikacji typu push. Wraz z rozwojem sieci i technologii z nią związanych, pojawia się potrzeba tworzenia serwisów dostarczających dane użytkownikom "w czasie rzeczywistym" i takich, które będą w stanie same dostarczać dane na dowolne urządzenie (przeglądarka, desktop, aplikacje mobilne). Całą sieć do tej pory opierała się głównie na protokole HTTP, który jest mechanizmem typu pull (klient wysyła request i otrzymuje odpowiedź od serwera). Serwis typu push działa tak, że otwiera połączenia od klientów i notyfikuje ich o zmianach w jakimś źródle danych (np. w tabeli bazy danych). Podobnie działają mechanizmy typu publish - subscribe (np. MSMQ), ale potrzebujemy czegoś, co będzie dobrze działało na każdej platformie i każdym urządzeniu.

Programowanie w SignalR daje właśnie taki model ideowy zapewniając dobór technologii odpowiadającej możliwościom urządzenia klienckiego. Serwisy typu push są w SignalR zaimplementowane na cztery sposoby, rozpoczynając od tych najmniej wydajnych, a kończąc na najwydajniejszych:

  1. Long polling - mechanizm cyklicznego odpytywania serwera AJAX-owymi zapytaniami. Zapytanie takie ma ustawiony długi timeout (np. 30 sekund), a serwer nie odpowiada na nie od razu, ale w momencie, gdy pojawią mu się jakieś dane do wysłania. Jeżeli serwer nie ma nic ciekawego do wysłania, to nie wysyła odpowiedzi, a klient ponowi żądanie za 30 sekund
  2. Forever frame - po stronie klienta pojawia się ukryty iFrame, który wysyła zapytanie do serwera. Serwer zwraca odpowiedzi z nagłówkiem Transfer-encoding: chunked, który pozwala na wysłanie odpowiedzi w kilku paczkach. Każda taka wiadomość jest wysyłana tylko wtedy, kiedy na serwerze pojawią się nowe dane. Serwer wysyła wiadomości, które wstrzykują skrypt wywołujący jakąś metodę po stronie klienta.
  3.       
  4. Server-sent events - jednokierunkowy model komunikacji, w którym serwer wysyła do klienta zdarzenia. Wykorzystuje ideę persistent connection (reużywania połączenia TCP do wysłania wielu requestów / responsów w oparciu o nagłówek connection: 'keep-alive'). Wiadomości takie wykorzystują specjalny content-type: text/event-stream, a po stronie klienta także obiekt EventSource
  5. WebSocket - komunikacja dwukierunkowa, oparta na prostym API WebSocket ze specyfikacji HTML5. Przeglądarka negocjuje z serwerem upgrade protokołu z HTTP/HTTPS na odpowiednio WS lub WSS i jeżeli serwer wyrazi zgodę (kod HTTP 101), to połaczenie TCP/IP zostanie użyte do otwarcia dwukierunkowego kanału pomiędzy klientem, a serwerem. Po stronie JS mamy do dyspozycji obiekt WebSocket.
SignalR może być osadzony w aplikacji ASP.NET lub jako self-host. Pracę z tym frameworkiem najlepiej rozpocząć od dodania kilku NuGetów:



Następnie tworzymy najprostszy rodzaj huba - echo, które będzie odpowiadało na klienckie wiadomości.

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            using (WebApp.Start<WsStartup>("http://localhost:1968"))
            {
                Console.WriteLine("Server running!");
                Console.ReadLine();
            }
        }
    }

    public class WsStartup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
            app.MapSignalR();
        }
    }

    [HubName("echo")]
    public class EchoHub : Hub
    {
        public string Call(string text)
        {
            return text + " from hub";
        }
    }
}

Wywołanie metody WebApp.Start("http://localhost:1968") powoduje zainicjalizowanie endpointów SignalR za pomocą klasy Startup pod wyspecyfikowanym adresem. Atrybut HubName określna przyjazną nazwę, po której będzie łączył się do niego klient. 

Najprostszy przykład kodu klienckiego (wysyłający wiadomość i wyświetlający odpowiedź) wygląda następująco:
 

<!DOCTYPE html>
<html >
<head>
    <title></title>
    <script src="Scripts/jquery-2.1.0.js"></script>
    <script src="Scripts/jquery.signalR-2.0.2.js"></script>
    <script src="/signalr/hubs"></script>
    <script>
        $(function () {
            var hub = $.connection.echo;
            $.connection.hub
                .start()
                .done(function () {
                    hub.server.call('Hello SignalR!').done(function(msg){
                      alert(msg);
                    });;
                });
        });
    </script>
</head>
<body>
</body>
</html>

Trzeci tag <script> wskazuje na dynamiczny endpoint /signalr/hubs wystawiony przez serwer. Endpoint ten generuje w locie kod JS na podstawie dostępnych hubów. Dzięki niemu możemy pobrać referencję do naszego huba ($.connection.echo). Następnie w asynchroniczny sposób zostaje wołana metoda start. Metoda ta zwraca obiekt promise, w którym możemy zasubskrybować się na metodzie done, gdzie możemy wołać kod z naszego huba.

Brak komentarzy:

Prześlij komentarz