Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

Asp.NET Core – SignalR Serisi #6 – Bağlantı Olayları

Merhaba,

SignalR mimarisi, Hub’lara yapılan bağlantıları yönetmek ve izleyebilmek için OnConnectedAsync ve OnDisconnectedAsync olmak üzere iki adet virtual metot sunmaktadır. Bu metotları override ederek, bir Hub’a bağlı olan tüm client’lardan haberdar olunabilmekte ve bütünsel işlemleri rahatlıkla gerçekleştirebilmekteyiz. Şimdi sırasıyla iki fonksiyonu inceleyelim;

  • OnConnectedAsync
    Bir client tarafından Hub’a bağlantı kurulduğu esnada tetiklenen fonksiyondur. Bağlantı kuran client’a dair connectionid vs. gibi bilgileri vermekte ve böylece tüm bağlantılar yönetilebilmekte ve izlenebilmektedir.

            public async override Task OnConnectedAsync()
            {
                await Clients.All.SendAsync("userJoined", $"{Context.ConnectionId}");
            }
    
  • OnDisconnectedAsync
    Bir client’ın Hub ile kurulmuş bağlantısının kopması neticesinde tetiklenen fonksiyondur. O anki eşzamanlı etkileşimde genel istatistiğin elde edilmesini sağlar.

            async public override Task OnDisconnectedAsync(Exception exception)
            {
                await Clients.All.SendAsync("userLeaved", $"{Context.ConnectionId}");
            }
    

Bağlantı olayları SignalR uygulamalarında loglama için elverişli fonksiyonlardır.

Örnek Uygulama

Yukarıdaki gibi ilgili fonksiyonları override etmiş olan bir SignalR hub server geliştirelim.

    public class MyHub : Hub
    {
        public async Task SendMessageAsync(string message)
        {
            await Clients.All.SendAsync("receiveMessage", message);
        }

        public async override Task OnConnectedAsync()
        {
            await Clients.All.SendAsync("userJoined", $"{Context.ConnectionId}");
        }

        async public override Task OnDisconnectedAsync(Exception exception)
        {
            await Clients.All.SendAsync("userLeaved", $"{Context.ConnectionId}");
        }
    }

Ardından ilgili server’a uygun jQuery ile bir client tasarlayalım.

<!DOCTYPE html>
<html>
<head>
   <script src="node_modules/@microsoft/signalr/dist/browser/signalr.min.js"></script>
   <script src="node_modules/jquery/dist/jquery.min.js"></script>
   <script>
      $(document).ready(() => {
         var connection = new signalR.HubConnectionBuilder()
            .withUrl("https://localhost:5001/myhub")
            .build();

         connection.start();

         $("button").click(() => {
            let message = $("#txtMessage").val();
            connection.invoke("SendMessageAsync", message)
               .catch(error => console.log("Mesaj gönderilirken hata alınmıştır."));
         });

         connection.on("receiveMessage", message => {
            $("#messages").append(`${message}<br>`);
         });

         connection.on("userJoined", connectionId => {
            $("div").html(`${connectionId} katıldı.`);
            setTimeout(() => {
               $("div").show(2000, () => {
                  $("div").hide(2000);
               })
            }, 2000);
         });

         connection.on("userLeaved", connectionId => {
            $("div").html(`${connectionId} ayrıldı.`);
            $("div").show(2000, () => {
               setTimeout(() => {
                  $("div").show(2000, () => {
                     $("div").hide(2000);
                  })
               }, 2000);
            })
         });
      });
   </script>
</head>
<body>
   <input type="text" id="txtMessage"> <button>Gönder</button>
   <ul id="messages">
   </ul>
   <div style="color:darkorange;background-color: dimgrey; width: 250px; display: none;">
   </div>
</body>
</html>

Birden fazla client yapılanmasıyla örneklendirmeyi çeşitlendirebilmek için aynı SignalR sunucusuna bağlantı sağlayan benzer nitelikte bir de Console Application tasarlayalım.

    class Program
    {
        static HubConnection connection;
        async static Task Main(string[] args)
        {
            connection = new HubConnectionBuilder().WithUrl("https://localhost:5001/myhub").Build();
            await connection.StartAsync();
            Console.WriteLine(connection.State);
            connection.On<string>("receiveMessage", message =>
             {
                 Console.WriteLine($"--->{message}");
             });

            connection.On<string>("userJoined", message =>
            {
                Console.WriteLine($"{message} katıldı.");
            });

            connection.On<string>("userLeaved", message =>
            {
                Console.WriteLine($"{message} ayrıldı.");
                Console.WriteLine("*****************************");
            });

            while (true)
            {
                Console.WriteLine("Gönderilecek mesajı yazınız.");
                await connection.InvokeAsync("SendMessageAsync", Console.ReadLine());
            }
        }
    }

Console uygulaması üzerinden SignalR’a nasıl bağlantı sağlandığını tüm detaylarıyla serimizin ileri ki makalelerinde ele alacağız. Keza yukarıdaki örnek ilgili konuya dair yeterince detay barındırsada, hangi kütüphanenin yüklenmesi gerektiği, hangi sınıfların ne işe yaradığı yahut hangi eventlerin kullanıldığı gibi teferruatları değerlendirmeyi ilgili makale(ler)ye bırakıyorum.

Test Edelim

Tüm bu işlemlerden sonra geliştirilen client uygulamalarından birkaç instance ayağa kaldıralım ve süreci test edelim.
Asp.NET Core – SignalR Serisi #6 - Bağlantı Olayları

Tüm Client’ları Listeleme

Server’a bağlı olan tüm client’ları listeleyebilmek için aşağıdaki gibi çalışabilirsiniz.

    public class MyHub : Hub
    {
        static List<string> clients = new List<string>();
        public async Task SendMessageAsync(string message)
        {
            await Clients.All.SendAsync("receiveMessage", message);
        }

        public async override Task OnConnectedAsync()
        {
            clients.Add(Context.ConnectionId);
            await Clients.All.SendAsync("clients", clients);
            await Clients.All.SendAsync("userJoined", $"{Context.ConnectionId}");
        }

        async public override Task OnDisconnectedAsync(Exception exception)
        {
            clients.Remove(Context.ConnectionId);
            await Clients.All.SendAsync("clients", clients);
            await Clients.All.SendAsync("userLeaved", $"{Context.ConnectionId}");
        }
    }

Yukarıdaki misalde görüldüğü üzere ‘clients’ isimli fonksiyon dinlendiği vakit sistemdeki mevcut client’ların bilgileri elde edilebilmektedir.

Örneğin;

         connection.on("clients", clients => {
            let lis = "";
            for (const client in clients) {
               lis += `<li>${clients[client]}</li>`;
            }
            $("#clients").html(lis);
         });
   <ul id="clients">
   </ul>

yukarıdaki gibi basit bir çalışma neticesinde,
Asp.NET Core – SignalR Serisi #6 - Bağlantı Olayları
şeklinde işlevselliği gözlemleyebilirsiniz.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Not : Örnek uygulama(ları) indirebilmek için buraya tıklayınız.

Bunlar da hoşunuza gidebilir...

9 Cevaplar

  1. Osman dedi ki:

    Merhaba Gencay Bey,

    Browser kapandığında .Net core da bu yapıyı tetikleyecek bir script var mı signalRda?

    • Gençay dedi ki:

      Merhaba,

      Browser kapatıldığında bağlantı kopacağı için ‘OnDisconnectedAsync’ metodu tetiklenecektir. Bu durumda işinizi ilgili fonksiyonda işleyebilir ve diğer client’ları konuya dair bilgilendirebilir yahut farklı mesajlar gönderebilirsiniz.

      • Osman dedi ki:

        Ama browser kapatıldığında script dosyasının tetiklenmesini istiyorum. Bu tetikleme işini

        await Clients.All.SendAsync(“disconnectSession”, sessionDisconnect);

        ” ile sağlıyorum. Bu yöntem dışında daha iyi bir yapı var mı?

  2. Emre dedi ki:

    Merhaba Gencay Hocam,
    Browser refresh yapıldığında da bağlantı kopuyor, disconnection oluyor, çevrimiçi chat sayfalarında refresh yapılsada konuşma devam ediyor. Bunu nasıl sağlayabiliriz. Login işlemi olmadığı için tokensız işlemler yapılıyor.

    • Gençay dedi ki:

      Merhaba,

      SignalR(ve esasında websocket) teknolojisi tarayıcı refresh yapıldığında ister istemez bağlantıyı koparım, ardından tekrar bağlantıyı sağlamaktadır. Bu durum kaçınılmazdır. Siz Cookie, JWT gibi değerlerden faydalanarak client’ın kimliğini tutabilirsiniz. Yani bu çalışmayı sizin yapıp halletmeniz gerekmektedir.

      Kolay gelsin.
      Sevgiler.

  3. Osman dedi ki:

    Merhaba Gencay Bey,

    ‘Page Refresh’ olduğu zaman bağlantı kopuyor ve OnDisconnectedAsync metodu tetikleniyor bunu engelleyebilir miyim?

  1. 16 Eylül 2020

    […] Asp.NET Core – SignalR Serisi #6 – Bağlantı Olayları […]

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir