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.
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,
ş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.
Merhaba Gencay Bey,
Browser kapandığında .Net core da bu yapıyı tetikleyecek bir script var mı signalRda?
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.
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ı?
Browser kapatıldığında tetiklensin istediğin script ilgili hub’a bağlı olan diğer client’lar değil mi?
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.
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.
Merhaba Gencay Bey,
‘Page Refresh’ olduğu zaman bağlantı kopuyor ve OnDisconnectedAsync metodu tetikleniyor bunu engelleyebilir miyim?
Merhaba,
Sanmıyorum. Araştırmak lazım.