Physical Address

304 North Cardinal St.
Dorchester Center, MA 02124

ASP.NET Core ile SignalR Öğrenme

Signal R, Microsoft tarafından geliştirilen bir kütüphanedir ve .NET uygulamalarına gerçek zamanlı web işlevselliği ekler. Çift yönlü iletişimi destekleyerek, sunucu ve istemci arasında anında veri akışı sağlar. WebSockets ile entegre çalışır ve desteklenmeyen durumlarda eski teknolojilere geçiş yapabilir, bu da onu çeşitli web uygulamaları için ideal kılar.
SignalR ile Gerçek Zamanlı Uygulama Geliştirme: Sunucu ve İstemci Uygulamalarının Oluşturulması

SignalR, Microsoft tarafından geliştirilen ve real-time (gerçek zamanlı) uygulama geliştirmeyi kolaylaştıran bir kütüphanedir. Bu yazıda, SignalR kullanarak sunucu ve istemci uygulamalarının nasıl geliştirileceğini adım adım ele alacağız.

1. SignalR Nedir?

SignalR, .NET geliştiricileri için geliştirilmiş, real-time web uygulamaları oluşturmayı kolaylaştıran bir kütüphanedir. SignalR, sunucu ile istemci arasında çift yönlü iletişim sağlayarak, mesajların anında iletilmesini mümkün kılar. Bu, özellikle chat uygulamaları, canlı veri güncellemeleri, oyunlar ve diğer real-time gereksinimlerinde oldukça faydalıdır.

2. Klasik Web Yaklaşımı ve SignalR

Klasik web uygulamalarında, sunucu ile istemci arasındaki iletişim genellikle HTTP istekleri üzerinden gerçekleştirilir. İstemci, sunucuya istek gönderir ve yanıt alır. Bu model, real-time uygulamalar için yeterli değildir çünkü sunucudan sürekli veri çekmek gereksinimi doğurur ve bu da performans ve kullanıcı deneyimi açısından sorunlara yol açabilir.

SignalR, bu sorunu çözmek için WebSocket protokolü üzerine inşa edilmiştir. WebSocket, sunucu ve istemci arasında sürekli açık bir bağlantı kurarak, iki tarafın da birbirine anında veri göndermesine olanak tanır. SignalR, bu bağlantıyı yönetir ve geliştiricilere kolay bir API sunar.

3. SignalR’ın Çalışma Mekanizması

SignalR’ın temelinde, Hub adı verilen bir yapı bulunur. Hub, sunucu ile istemci arasında iletişimi yönetir. İstemciler Hub’a bağlanır ve sunucu, Hub üzerinden gelen mesajları diğer istemcilere iletir. Hub sınıfları, sunucu tarafında oluşturulur ve istemciler, bu Hub’lara bağlanarak sunucu ile iletişim kurar.

4. SignalR İle Uygulama Geliştirme
4.1. Sunucu Tarafı Kurulumu

SignalR kullanarak bir sunucu uygulaması geliştirmek için aşağıdaki adımları takip etmeliyiz:

1. Adım: Proje Oluşturma

Öncelikle, ASP.NET Core uygulaması oluşturuyoruz. Visual Studio veya .NET CLI kullanarak boş bir ASP.NET Core uygulaması oluşturabilirsiniz.

dotnet new web -n SignalRExample

2. Adım: SignalR Kütüphanesini Yükleme

Proje oluşturulduktan sonra, SignalR kütüphanesini projeye dahil etmemiz gerekiyor. Bu, NuGet paket yöneticisi kullanılarak yapılabilir:

dotnet add package Microsoft.AspNetCore.SignalR

3. Adım: Hub Sınıfının Oluşturulması

SignalR uygulamalarında, sunucu tarafında bir Hub sınıfı tanımlanır. Bu sınıf, istemcilerden gelen mesajları alır ve diğer istemcilere iletir.

using Microsoft.AspNetCore.SignalR;

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

Yukarıdaki kodda, ChatHub sınıfı oluşturduk. Bu sınıf, istemcilerden gelen mesajları alır ve diğer tüm istemcilere bu mesajları iletir. SendMessage metodu, istemciden bir kullanıcı adı ve mesaj alır ve bu mesajı diğer istemcilere iletir.

4. Adım: SignalR’ı Başlatma

SignalR’ı kullanabilmek için, Startup.cs dosyasında gerekli ayarları yapmamız gerekiyor.

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddSignalR(); // SignalR hizmetini ekliyoruz.
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
        endpoints.MapHub<ChatHub>("/chathub"); // SignalR Hub'ını tanımlıyoruz.
    });
}

Bu yapılandırmada, SignalR’ı servislere ekledik ve uygulama pipeline’ına SignalR Hub’ını ekledik. MapHub<ChatHub>("/chathub") satırı ile ChatHub sınıfını /chathub endpoint’i ile ilişkilendirdik.

4.2. İstemci Tarafı Kurulumu

SignalR istemci tarafında, JavaScript kullanarak sunucuya bağlanabilir ve mesaj gönderebiliriz.

1. Adım: SignalR Kütüphanelerini Dahil Etme

İstemci tarafında, SignalR JavaScript kütüphanesini kullanmamız gerekiyor. Bu kütüphaneyi projeye eklemek için HTML dosyanıza aşağıdaki script etiketlerini ekleyin:

<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/5.0.9/signalr.min.js"></script>

2. Adım: SignalR Bağlantısı Oluşturma

SignalR ile sunucuya bağlanmak için bir bağlantı oluşturmalıyız. Bu bağlantı, Hub ile iletişim kurmamızı sağlar.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .build();

connection.start().catch(err => console.error(err.toString()));

3. Adım: Mesaj Gönderme ve Alma

Artık istemci, sunucuya mesaj gönderebilir ve sunucudan gelen mesajları alabilir.

document.getElementById("sendButton").addEventListener("click", function (event) {
    const user = document.getElementById("userInput").value;
    const message = document.getElementById("messageInput").value;
    connection.invoke("SendMessage", user, message).catch(err => console.error(err.toString()));
    event.preventDefault();
});

connection.on("ReceiveMessage", function (user, message) {
    const msg = user + " says " + message;
    const li = document.createElement("li");
    li.textContent = msg;
    document.getElementById("messagesList").appendChild(li);
});

Yukarıdaki kodda, sendButton butonuna tıklanıldığında, istemci sunucuya bir mesaj gönderir (SendMessage metodunu çağırır). Sunucudan bir mesaj geldiğinde (ReceiveMessage), bu mesaj istemci üzerinde bir listeye eklenir.

SignalR ile Gerçek Zamanlı Uygulamalar Geliştirme: Otomatik Bağlantı Ayarları ve Durum Yönetimi Fonksiyonları

SignalR, gerçek zamanlı (real-time) uygulamalar geliştirmek için kullanılan güçlü bir kütüphanedir. Bu yazıda, SignalR’ın otomatik bağlantı konfigürasyonları ve durum fonksiyonları ile ilgili detayları inceleyeceğiz. Otomatik bağlantı denemeleri, bağlantı durumu takibi ve bu süreçte kullanıcıya bilgi verme gibi önemli konuları ele alacağız.

1. SignalR’da Otomatik Bağlantı Konfigürasyonu

SignalR, istemci ve sunucu arasında sürekli bir bağlantı kurarak gerçek zamanlı iletişimi sağlar. Ancak bazı durumlarda bu bağlantı kopabilir veya baştan kurulamayabilir. Bu gibi durumlarda bağlantının otomatik olarak tekrar kurulması gerekebilir.

1.1. Otomatik Bağlantı Yenileme (Reconnect)

Bağlantının kopması durumunda, SignalR’ın otomatik olarak bağlantıyı tekrar denemesi için withAutomaticReconnect fonksiyonu kullanılır. Bu fonksiyon, belirli aralıklarla bağlantıyı tekrar denemek için yapılandırılabilir.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .withAutomaticReconnect([0, 2000, 10000, 30000])
    .build();

Yukarıdaki örnekte, withAutomaticReconnect fonksiyonu dört farklı deneme süresi ile yapılandırılmıştır:

  • İlk deneme hemen yapılır (0 ms).
  • İkinci deneme 2 saniye sonra yapılır.
  • Üçüncü deneme 10 saniye sonra yapılır.
  • Dördüncü deneme 30 saniye sonra yapılır.

Eğer 30 saniye içinde bağlantı tekrar sağlanamazsa, SignalR bağlantıyı tamamen keser ve yeniden denemeyecektir.

1.2. Özel Reconnect Süreleri Belirleme

Bağlantı denemeleri için özel süreler tanımlamak mümkündür. Örneğin, bağlantı denemelerini her bir saniyede bir tekrar etmek isteyebilirsiniz:

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .withAutomaticReconnect([1000, 1000, 3000, 5000])
    .build();

Bu yapılandırma, ilk denemenin bir saniye sonra, ikinci denemenin yine bir saniye sonra, üçüncü denemenin üç saniye sonra ve dördüncü denemenin beş saniye sonra yapılmasını sağlar.

2. Bağlantı Durumlarını Yönetme

SignalR, bağlantı durumlarına göre çeşitli olaylar (events) tetikler. Bu olaylar, bağlantı durumu değişikliklerini izlemek ve kullanıcıya bu durumu bildirmek için kullanılabilir.

2.1. onreconnecting Olayı

Bağlantının koptuğu ve yeniden bağlanma denemelerinin başladığı durumlarda onreconnecting olayı tetiklenir. Bu olay, kullanıcıya bağlantının yeniden kurulmaya çalışıldığını bildirmek için kullanılabilir.

connection.onreconnecting((error) => {
    console.log("Bağlantı koptu, yeniden bağlanmaya çalışılıyor...");
    document.getElementById("status").textContent = "Bağlantı koptu, yeniden bağlanmaya çalışılıyor...";
});
2.2. onreconnected Olayı

Bağlantı yeniden sağlandığında onreconnected olayı tetiklenir. Bu olay, bağlantının başarıyla yeniden kurulduğunu bildirmek için kullanılabilir.

connection.onreconnected((connectionId) => {
    console.log("Bağlantı yeniden kuruldu.");
    document.getElementById("status").textContent = "Bağlantı yeniden kuruldu.";
});
2.3. onclose Olayı

Bağlantı denemeleri başarısız olursa ve SignalR bağlantıyı tamamen kapatırsa onclose olayı tetiklenir. Bu olay, kullanıcıya bağlantının kesildiğini bildirmek için kullanılabilir.

connection.onclose((error) => {
    console.log("Bağlantı tamamen kesildi.");
    document.getElementById("status").textContent = "Bağlantı tamamen kesildi.";
});
3. Kullanıcıya Durum Bildirimi Yapma

Bağlantı durumlarını takip etmek ve kullanıcıya bilgi vermek için HTML’de basit bir durum göstergesi (status indicator) oluşturabiliriz.

<div id="status" style="display:none; color: white; background-color: red; padding: 10px;"></div>

Bağlantı durumu değiştiğinde bu durumu kullanıcıya gösterecek şekilde status div’ini güncelleyebiliriz. Örneğin:

// onreconnecting olayında
document.getElementById("status").style.display = "block";
document.getElementById("status").style.backgroundColor = "orange";
document.getElementById("status").textContent = "Bağlantı koptu, yeniden bağlanmaya çalışılıyor...";

// onreconnected olayında
document.getElementById("status").style.backgroundColor = "green";
document.getElementById("status").textContent = "Bağlantı yeniden kuruldu.";

// onclose olayında
document.getElementById("status").style.backgroundColor = "red";
document.getElementById("status").textContent = "Bağlantı tamamen kesildi.";

Bu şekilde, kullanıcıya bağlantı durumu hakkında anında bilgi verebilirsiniz.

4. Bağlantı Durumuna Göre Farklı Operasyonlar Yapma

Bağlantı durumlarına göre farklı işlemler gerçekleştirmek için SignalR olaylarını kullanabiliriz. Örneğin, bağlantı koptuğunda kullanıcıya belirli bir mesaj göstermek veya yeniden bağlanma denemeleri sırasında belirli bir animasyon oynatmak gibi.

connection.onreconnecting((error) => {
    // Yeniden bağlanma denemesi başlamadan önce yapılacak işlemler
    console.log("Bağlantı kopmuş olabilir, yeniden bağlanıyor...");
    // Kullanıcıya bilgi verme veya UI güncellemeleri yapma
});

connection.onreconnected((connectionId) => {
    // Bağlantı yeniden sağlandığında yapılacak işlemler
    console.log("Bağlantı tekrar kuruldu, ID: " + connectionId);
    // UI'yı güncelleme
});

connection.onclose((error) => {
    // Bağlantı tamamen kesildiğinde yapılacak işlemler
    console.log("Bağlantı tamamen kapatıldı.");
    // Kullanıcıya bilgi verme veya UI güncellemeleri yapma
});

SignalR ile Gerçek Zamanlı Uygulama Geliştirme: Bağlantı Olayları ve Tüm İstemcilerin Listelenmesi

SignalR, gerçek zamanlı uygulamalar geliştirmek için kullanılan güçlü bir kütüphanedir. Bu yazıda, SignalR kullanarak bağlantı olaylarını yönetme ve sistemdeki tüm client’ları listeleme konularını derinlemesine inceleyeceğiz. Bu süreçte, bağlantıların izlenmesi, client’ların haberdar edilmesi ve sistemdeki tüm client’ların listelenmesi gibi önemli adımları ele alacağız.

1. SignalR’da Bağlantı Olayları (Connection Events)

SignalR’da, bir client (istemci) sunucuya bağlandığında veya bağlantısını kestiğinde belirli olaylar (events) tetiklenir. Bu olaylar, bağlantıların izlenmesi ve yönetilmesi açısından önemlidir.

1.1. OnConnectedAsync Olayı

OnConnectedAsync olayı, bir client sunucuya başarılı bir şekilde bağlandığında tetiklenir. Bu olay sayesinde, yeni bir client sisteme bağlandığında gerekli işlemleri yapabilir ve diğer client’ları bu bağlantıdan haberdar edebilirsiniz.

public class ChatHub : Hub
{
    public override async Task OnConnectedAsync()
    {
        // Yeni bir client bağlandığında çalışacak kodlar
        await Clients.All.SendAsync("UserConnected", Context.ConnectionId);
        await base.OnConnectedAsync();
    }
}

Bu örnekte, yeni bir client bağlandığında tüm diğer client’lara UserConnected adında bir olay tetiklenir ve bağlanan client’ın ConnectionId değeri gönderilir.

1.2. OnDisconnectedAsync Olayı

OnDisconnectedAsync olayı, bir client sunucu ile bağlantısını kestiğinde veya bağlantısı kesildiğinde tetiklenir. Bu olay, bir client’ın sistemden çıktığında yapılması gereken işlemleri gerçekleştirmek için kullanılır.

public class ChatHub : Hub
{
    public override async Task OnDisconnectedAsync(Exception exception)
    {
        // Bir client bağlantısını kestiğinde çalışacak kodlar
        await Clients.All.SendAsync("UserDisconnected", Context.ConnectionId);
        await base.OnDisconnectedAsync(exception);
    }
}

Yukarıdaki örnekte, bir client bağlantısını kestiğinde tüm diğer client’lara UserDisconnected adında bir olay tetiklenir ve bağlantıyı kesen client’ın ConnectionId değeri gönderilir.

2. Client’ların Takibi ve Bağlantı Durumlarını Yönetme

Sistemde hangi client’ların bağlı olduğunu ve bağlantıların ne zaman kesildiğini izlemek için, bu olayları kullanarak bir koleksiyon (list) oluşturabilirsiniz. Bu koleksiyon, bağlanan ve ayrılan client’ları izlemek için kullanılır.

2.1. Bağlanan Client’ları İzleme

Bağlanan tüm client’ları izlemek ve bir listeye eklemek için OnConnectedAsync olayını kullanabilirsiniz:

public class ChatHub : Hub
{
    private static List<string> connectedClients = new List<string>();

    public override async Task OnConnectedAsync()
    {
        connectedClients.Add(Context.ConnectionId);
        await Clients.All.SendAsync("UpdateClientList", connectedClients);
        await base.OnConnectedAsync();
    }
}

Bu kodda, bağlanan her client’ın ConnectionId değeri connectedClients listesine eklenir ve ardından bu liste tüm client’lara gönderilir.

2.2. Ayrılan Client’ları İzleme

Client bağlantısını kestiğinde, connectedClients listesinden çıkarılması ve diğer client’lara güncellenmiş listenin gönderilmesi gerekir:

public class ChatHub : Hub
{
    public override async Task OnDisconnectedAsync(Exception exception)
    {
        connectedClients.Remove(Context.ConnectionId);
        await Clients.All.SendAsync("UpdateClientList", connectedClients);
        await base.OnDisconnectedAsync(exception);
    }
}

Bu kodda, ayrılan client’ın ConnectionId değeri connectedClients listesinden çıkarılır ve güncellenmiş liste tüm client’lara gönderilir.

3. Client’lar Arasında İletişim Sağlama

SignalR kullanarak client’lar arasında gerçek zamanlı iletişim sağlamak için, server’da tetiklenen olayları client tarafında dinlemek gerekir.

3.1. Client Tarafında Olayları Dinleme

Client tarafında, server’dan gönderilen UserConnected, UserDisconnected ve UpdateClientList gibi olayları dinleyebilir ve buna göre kullanıcı arayüzünü (UI) güncelleyebilirsiniz.

const connection = new signalR.HubConnectionBuilder().withUrl("/chathub").build();

connection.on("UserConnected", function (connectionId) {
    console.log("User connected: " + connectionId);
});

connection.on("UserDisconnected", function (connectionId) {
    console.log("User disconnected: " + connectionId);
});

connection.on("UpdateClientList", function (clientList) {
    // Tüm client'ları listeleme
    const clientListElement = document.getElementById("clientList");
    clientListElement.innerHTML = "";
    clientList.forEach(clientId => {
        const listItem = document.createElement("li");
        listItem.textContent = clientId;
        clientListElement.appendChild(listItem);
    });
});

Bu JavaScript kodunda, server tarafından gönderilen olaylar dinlenir ve client’lar arası iletişim sağlanır.

4. Tüm Client’ları Listeleme

SignalR kullanarak sistemdeki tüm client’ları listelemek ve bu listeyi güncel tutmak için yukarıdaki kodları kullanabilirsiniz. Bağlanan ve ayrılan her client, bu listeye eklenir veya çıkarılır ve güncel liste tüm client’lara gönderilir.

4.1. HTML ile Client Listesini Gösterme

Client listesi, basit bir HTML liste (ul) yapısı ile kullanıcıya gösterilebilir:

<ul id="clientList"></ul>

Bu liste, UpdateClientList olayı tetiklendiğinde JavaScript tarafından güncellenir.

SignalR ile Gerçek Zamanlı Uygulama Geliştirme: IHubContext Arayüzü

SignalR, ASP.NET Core uygulamaları için gerçek zamanlı web işlevselliği sunan güçlü bir kütüphanedir. Bu yazıda, SignalR’ın iki önemli özelliği olan IHubContext arayüzü ve Strongly Typed Hubs (Türü Belirlenmiş Hubs) özelliklerini detaylı olarak ele alacağız. Bu özellikler, SignalR kullanarak daha esnek, güvenli ve hataya dayanıklı uygulamalar geliştirmenizi sağlar.

1. IHubContext Arayüzü

IHubContext, SignalR’da bir Hub’ın (merkezi iletişim noktası) dışında, farklı katmanlarda veya iş mantığında client’larla (istemcilerle) iletişim kurabilmenizi sağlayan bir arayüzdür. Bu arayüz, Hub sınıflarının dışında da SignalR bağlantıları üzerinden mesaj göndermenize olanak tanır.

1.1. IHubContext Nedir ve Neden Kullanılır?

SignalR Hub sınıfları, doğrudan client’lar ile iletişim kurmak için tasarlanmıştır. Ancak, bazen iş mantığınızda veya farklı sınıflarda, Hub sınıfının dışında SignalR üzerinden client’lara mesaj göndermeniz gerekebilir. Bu durumda, IHubContext arayüzü devreye girer.

IHubContext, Hub’ın dışında SignalR işlevlerini kullanarak client’larla iletişim kurmanıza olanak tanır. Bu, özellikle bağımsız sınıflarda veya servislerde SignalR işlevlerini kullanmanız gerektiğinde oldukça yararlıdır.

1.2. IHubContext Kullanımı

Öncelikle, IHubContext arayüzünü kullanarak bir SignalR Hub’ı dışında client’lara nasıl mesaj gönderebileceğinizi inceleyelim.

public class MyBusinessService
{
    private readonly IHubContext<MyHub> _hubContext;

    public MyBusinessService(IHubContext<MyHub> hubContext)
    {
        _hubContext = hubContext;
    }

    public async Task SendMessageToAllClients(string message)
    {
        await _hubContext.Clients.All.SendAsync("ReceiveMessage", message);
    }
}

Bu örnekte, MyBusinessService adında bir servis sınıfı oluşturduk ve bu sınıf içerisinde SignalR Hub’ına bağımlı bir IHubContext referansı tanımladık. SendMessageToAllClients metodu, IHubContext arayüzünü kullanarak tüm bağlı client’lara bir mesaj göndermektedir.

1.3. IHubContext ile Dependency Injection

ASP.NET Core uygulamalarında IHubContext, Dependency Injection (Bağımlılık Enjeksiyonu) mekanizması ile sağlanır. Bu, IHubContext arayüzünün ilgili sınıflarda otomatik olarak enjekte edilmesini sağlar.

public void ConfigureServices(IServiceCollection services)
{
    services.AddSignalR();
    services.AddTransient<MyBusinessService>();
}

Yukarıdaki kod, MyBusinessService sınıfını bağımlılık olarak enjekte edilebilir hale getirir. Bu sınıfı bir Controller içinde veya başka bir serviste kullanabilirsiniz.

2. Strongly Typed Hubs (Türü Belirlenmiş Hubs)

SignalR’da Strongly Typed Hubs özelliği, client’lar ile server arasında daha güvenli ve hatasız bir iletişim kurmanıza yardımcı olur. Bu özellik, SignalR Hub’larında kullanılan metotların adlarını metinsel olarak değil, türü belirlenmiş bir arayüz aracılığıyla tanımlamanızı sağlar.

2.1. Strongly Typed Hubs Nedir ve Neden Kullanılır?

Strongly Typed Hubs, client ile server arasındaki iletişimde metin tabanlı hataları azaltmak ve derleme zamanında hataların tespit edilmesini sağlamak amacıyla kullanılır. Normalde SignalR’da metot isimleri metin olarak belirtilir ve bu, yazım hatalarına ve diğer sorunlara yol açabilir. Strongly Typed Hubs sayesinde bu metotlar bir arayüzde tanımlanır ve Hub’larda bu arayüzler üzerinden çağrılır.

2.2. Strongly Typed Hubs Kullanımı

Öncelikle, client’lar için bir arayüz tanımlayarak başlayalım:

public interface IClientMethods
{
    Task ReceiveMessage(string message);
    Task UserJoined(string userName);
    Task UserLeft(string userName);
}

Bu arayüz, client’ların server’dan alabileceği metotları tanımlar. Şimdi bu arayüzü SignalR Hub’ımıza uygulayalım:

public class MyHub : Hub<IClientMethods>
{
    public async Task SendMessageToAll(string message)
    {
        await Clients.All.ReceiveMessage(message);
    }
}

Yukarıdaki örnekte, MyHub sınıfı Hub<IClientMethods> olarak tanımlanmıştır. Bu, ReceiveMessage, UserJoined ve UserLeft metotlarının artık metin olarak değil, türü belirlenmiş bir arayüz (interface) üzerinden çağrılabileceği anlamına gelir.

2.3. Strongly Typed Hubs ile Güvenli İletişim

Strongly Typed Hubs, metot isimlerinin yazım hatalarını önler ve kodun daha okunabilir olmasını sağlar. Bu sayede, derleme zamanında hatalar tespit edilerek runtime (çalışma zamanı) hataları en aza indirilir.

SignalR ile Gerçek Zamanlı Uygulama Geliştirme: İstemci Türleri ve Kullanılan Yöntemler

SignalR, ASP.NET Core projelerinde gerçek zamanlı web uygulamaları geliştirmenizi sağlayan güçlü bir kütüphanedir. Bu yazıda, SignalR’ın sunduğu Clients türleri ve bu türlerin kullanıldığı metotları detaylı olarak ele alacağız. Bu özellikler, farklı senaryolar için esnek ve özelleştirilmiş iletişim kurmanızı sağlar.

1. Clients Türleri

SignalR, client’lara mesaj gönderirken kullanabileceğiniz farklı türler sunar. Bu türler, hangi client’lara mesaj gönderileceğini kontrol etmenize olanak tanır. SignalR’da başlıca üç tür client vardır:

  1. Caller: Mesajı gönderen client’ı temsil eder. Yani, bir mesaj gönderildiğinde bu mesaj sadece gönderen client’a iletilir.
  2. All: Mesajı gönderen client dahil, tüm client’lara mesaj gönderir.
  3. Others: Mesajı gönderen client hariç, diğer tüm client’lara mesaj gönderir.
1.1. Caller (Gönderen Client)

Caller, yalnızca mesajı gönderen client’a mesaj iletilmesini sağlar. Örneğin, bir client kendi gönderdiği mesajın sonucunu sadece kendisi görmek istediğinde bu tür kullanılır.

public async Task SendMessageToCaller(string message)
{
    await Clients.Caller.SendAsync("ReceiveMessage", message);
}

Bu örnekte, SendMessageToCaller metodu ile sadece mesajı gönderen client’a mesaj iletilir. Diğer client’lar bu mesajı almaz.

1.2. All (Tüm Client’lar)

All, mesajı gönderen dahil tüm client’lara mesaj gönderir. Bu tür, tüm client’ların aynı mesajı almasını istediğiniz senaryolarda kullanılır.

public async Task SendMessageToAll(string message)
{
    await Clients.All.SendAsync("ReceiveMessage", message);
}

Bu örnekte, SendMessageToAll metodu ile mesaj, bağlı olan tüm client’lara gönderilir.

1.3. Others (Diğer Client’lar)

Others, mesajı gönderen client hariç diğer tüm client’lara mesaj gönderir. Örneğin, bir gruba mesaj göndermek istediğinizde, mesajı gönderen hariç diğer tüm grup üyelerine mesaj iletilir.

public async Task SendMessageToOthers(string message)
{
    await Clients.Others.SendAsync("ReceiveMessage", message);
}

Bu örnekte, SendMessageToOthers metodu ile mesaj, gönderen client hariç diğer tüm client’lara gönderilir.

2. Client Türleri ile Çalışma Senaryoları

SignalR, daha karmaşık senaryolar için de metotlar sunar. Bu metotlar, belirli gruplara veya client’lara mesaj göndermenizi sağlar. Bu metotlar arasında Client, Group, GroupExcept, Clients, User, Users gibi fonksiyonlar bulunur.

2.1. Client (Belirli Client)

Client, belirli bir client’a mesaj göndermenizi sağlar. Bu client, ConnectionId ile tanımlanır.

public async Task SendMessageToClient(string connectionId, string message)
{
    await Clients.Client(connectionId).SendAsync("ReceiveMessage", message);
}

Bu örnekte, SendMessageToClient metodu ile belirli bir client’a (connectionId ile tanımlanan) mesaj gönderilir.

2.2. Group (Belirli Grup)

Group, belirli bir gruba mesaj göndermenizi sağlar. Grup üyeliği, client’ların gruplara eklenmesi veya çıkarılması ile kontrol edilir.

public async Task SendMessageToGroup(string groupName, string message)
{
    await Clients.Group(groupName).SendAsync("ReceiveMessage", message);
}

Bu örnekte, SendMessageToGroup metodu ile belirli bir gruba (groupName ile tanımlanan) mesaj gönderilir. Grup dışındaki client’lar bu mesajı almaz.

2.3. GroupExcept (Belirli Client’lar Hariç Grup)

GroupExcept, bir gruba mesaj gönderirken, belirli client’ların bu mesajı almasını engeller. Örneğin, bir gruba mesaj göndermek istiyorsunuz ama bazı client’lar bu mesajı almayacak.

public async Task SendMessageToGroupExcept(string groupName, string[] excludedConnectionIds, string message)
{
    await Clients.GroupExcept(groupName, excludedConnectionIds).SendAsync("ReceiveMessage", message);
}

Bu örnekte, SendMessageToGroupExcept metodu ile belirli bir gruba (groupName) mesaj gönderilir, ancak excludedConnectionIds ile belirtilen client’lar bu mesajı almaz.

2.4. Groups (Birden Çok Grup)

Groups, birden fazla gruba aynı anda mesaj göndermenizi sağlar.

public async Task SendMessageToGroups(string[] groupNames, string message)
{
    await Clients.Groups(groupNames).SendAsync("ReceiveMessage", message);
}

Bu örnekte, SendMessageToGroups metodu ile belirtilen gruplara aynı anda mesaj gönderilir.

3. Kullanılan Metotlar

SignalR’da client türlerini kullanırken, genellikle SendAsync metodu kullanılır. Bu metot, client’lara belirli bir metodu tetiklemeleri için mesaj gönderir.

3.1. SendAsync Metodu

SendAsync, belirli bir metodu client’larda tetiklemek için kullanılır.

public async Task SendMessageToAll(string message)
{
    await Clients.All.SendAsync("ReceiveMessage", message);
}

Yukarıdaki örnekte, ReceiveMessage metodu, tüm client’larda tetiklenir ve message parametresi iletilir.

3.2. Invoke Metodu

SignalR, sunucudan client’a veri göndermenin yanı sıra client’tan sunucuya veri göndermeyi de destekler. Bu durumda InvokeAsync metodu kullanılır. Ancak genellikle server-to-client iletişimi için SendAsync daha yaygındır.

4. Örnek Senaryolar

Aşağıda, farklı senaryolar için SignalR’da kullanılabilecek kod örnekleri verilmiştir.

4.1. Basit Chat Uygulaması

Bu örnekte, bir chat uygulamasında tüm client’lara mesaj göndermek için Clients.All kullanılır:

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}
4.2. Belirli Bir Gruba Mesaj Gönderme

Bir gruba mesaj göndermek için Clients.Group kullanılır:

public class ChatHub : Hub
{
    public async Task SendMessageToGroup(string groupName, string user, string message)
    {
        await Clients.Group(groupName).SendAsync("ReceiveMessage", user, message);
    }

    public async Task AddToGroup(string groupName)
    {
        await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
    }

    public async Task RemoveFromGroup(string groupName)
    {
        await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
    }
}
4.3. Kullanıcıya Göre Mesaj Gönderme

Belirli bir kullanıcıya mesaj göndermek için Clients.User kullanılır:

public async Task SendMessageToUser(string userId, string message)
{
    await Clients.User(userId).SendAsync("ReceiveMessage", message);
}

SignalR İle Realtime Uygulama Geliştirme

SignalR, ASP.NET Core içerisinde yer alan, web uygulamalarında gerçek zamanlı (realtime) etkileşimler gerçekleştirebilmek için kullanılan bir kütüphanedir. Bu makalede, SignalR ile bir chat uygulaması geliştirmenin adımlarını inceleyeceğiz.

1. Uygulama Tasarımı ve Stratejisi

Uygulamanın temel tasarımında, kullanıcılar belirli odalara (gruplar) katılarak mesajlaşabilecekler. Uygulama, kullanıcının giriş yapmasıyla başlayacak ve kullanıcı adı sisteme kaydedilerek bir bağlantı (connection) kurulacak. Bağlantı sağlandığında, kullanıcının girdiği isim ile connection ID eşleştirilecek ve bu isim, kullanıcıya özgü işlemlerde kullanılacak.

Uygulamanın Temel Adımları:

  1. Kullanıcı, giriş yaptıktan sonra bir kullanıcı adı girer.
  2. Kullanıcı adı, connection ID ile eşleştirilir ve bu bilgi sistemde tutulur.
  3. Kullanıcı, mevcut odalardan birine katılır veya yeni bir oda oluşturur.
  4. Oda (grup) içinde kullanıcılar mesajlaşabilir. Mesajlar, kullanıcıların isimleriyle birlikte gruba gönderilir.
  5. Kullanıcı bir odaya katıldığında, bu bilgi diğer kullanıcılara bildirilir.
2. SignalR Hub Sınıfının Oluşturulması

SignalR’da gerçek zamanlı iletişim için bir Hub sınıfı oluşturulur. Bu sınıf, istemci ve sunucu arasındaki iletişimi yönetir. Örneğin, bir chat uygulaması için bir ChatHub sınıfı oluşturulabilir.

public class ChatHub : Hub
{
    private static readonly List<UserConnection> _connections = new List<UserConnection>();

    public async Task SendMessage(string message, string groupName)
    {
        var user = _connections.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);
        if (user != null && !string.IsNullOrEmpty(groupName))
        {
            await Clients.Group(groupName).SendAsync("ReceiveMessage", user.Username, message);
        }
    }

    public async Task JoinGroup(string groupName)
    {
        var user = _connections.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);
        if (user != null)
        {
            await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
            await Clients.Group(groupName).SendAsync("UserJoined", user.Username);
        }
    }

    public override Task OnConnectedAsync()
    {
        _connections.Add(new UserConnection
        {
            ConnectionId = Context.ConnectionId,
            Username = Context.GetHttpContext().Request.Query["username"]
        });
        return base.OnConnectedAsync();
    }

    public override Task OnDisconnectedAsync(Exception exception)
    {
        var user = _connections.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);
        if (user != null)
        {
            _connections.Remove(user);
        }
        return base.OnDisconnectedAsync(exception);
    }
}

public class UserConnection
{
    public string ConnectionId { get; set; }
    public string Username { get; set; }
}
3. Kullanıcı ve Oda Yönetimi

Her kullanıcı sisteme giriş yaptığında bir connection ID ile eşleştirilir ve bu bilgi sunucuda bir listede saklanır. Aynı şekilde, kullanıcılar belirli odalara (gruplar) katıldığında, bu bilgi de sunucu tarafından takip edilir. Örneğin, kullanıcılar odalara katıldığında veya odalardan ayrıldığında diğer kullanıcılar bilgilendirilir.

public async Task JoinRoom(string roomName)
{
    await Groups.AddToGroupAsync(Context.ConnectionId, roomName);
    await Clients.Group(roomName).SendAsync("ReceiveMessage", $"{Context.ConnectionId} has joined the group {roomName}.");
}

public async Task LeaveRoom(string roomName)
{
    await Groups.RemoveFromGroupAsync(Context.ConnectionId, roomName);
    await Clients.Group(roomName).SendAsync("ReceiveMessage", $"{Context.ConnectionId} has left the group {roomName}.");
}
4. Mesajlaşma Fonksiyonu

Kullanıcılar, odalara katıldıklarında veya bireysel olarak diğer kullanıcılara mesaj gönderebilirler. Mesajlar, kullanıcının ismiyle birlikte ilgili odaya veya kullanıcıya gönderilir.

public async Task SendMessageToGroup(string groupName, string message)
{
    var user = _connections.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);
    if (user != null)
    {
        await Clients.Group(groupName).SendAsync("ReceiveMessage", user.Username, message);
    }
}

public async Task SendMessageToUser(string targetUser, string message)
{
    var targetConnection = _connections.FirstOrDefault(x => x.Username == targetUser);
    if (targetConnection != null)
    {
        await Clients.Client(targetConnection.ConnectionId).SendAsync("ReceiveMessage", Context.User.Identity.Name, message);
    }
}
5. UI ve SignalR Bağlantısı

Kullanıcı arayüzünde (UI) kullanıcının mesaj gönderebilmesi ve odalar arasında geçiş yapabilmesi için gerekli butonlar ve event handler’lar tanımlanır.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .build();

connection.on("ReceiveMessage", (username, message) => {
    const msg = username + " says " + message;
    const li = document.createElement("li");
    li.textContent = msg;
    document.getElementById("messagesList").appendChild(li);
});

document.getElementById("sendButton").addEventListener("click", event => {
    const message = document.getElementById("messageInput").value;
    const groupName = document.getElementById("groupInput").value;
    connection.invoke("SendMessageToGroup", groupName, message).catch(err => console.error(err.toString()));
    event.preventDefault();
});

connection.start().catch(err => console.error(err.toString()));

SignalR İle Realtime Uygulama Geliştirme

SignalR ile Realtime (Gerçek Zamanlı) Uygulama Geliştirme başlığı altında, veritabanındaki değişiklikleri anlık olarak yakalayabilen bir uygulama geliştirmenin tüm adımlarını detaylandırarak anlatacağım. Bu süreçte, özellikle SignalR, Entity Framework, SQL Server Service Broker gibi teknolojiler kullanarak, veritabanındaki değişikliklerin anlık olarak nasıl takip edileceğini ve bu değişikliklerin kullanıcı arayüzüne gerçek zamanlı olarak nasıl yansıtılacağını adım adım inceleyeceğiz.

Adım 1: Proje Kurulumu ve Genel Yapı

Öncelikle, bir Angular frontend ve bir ASP.NET Core backend uygulaması oluşturacağız. Frontend tarafında Angular kullanılmasının sebebi, SignalR ile entegrasyonun kolaylıkla yapılabilmesi ve kullanıcıya anlık geri bildirimler sunabilmemizdir. Backend tarafında ise ASP.NET Core ile SignalR’ı kullanarak veritabanı değişikliklerini anlık olarak takip edeceğiz.

Angular Uygulaması Oluşturma

Angular uygulamasını oluşturmak için aşağıdaki adımları izleyebilirsiniz:

ng new RealTimeApp
cd RealTimeApp
ng add @aspnet/signalr

Bu komutlarla Angular projemizi oluşturuyoruz ve SignalR için gerekli olan kütüphaneyi projeye dahil ediyoruz.

ASP.NET Core Uygulaması Oluşturma

Aşağıdaki komutları kullanarak ASP.NET Core projemizi oluşturabiliriz:

dotnet new webapi -n RealTimeAPI
cd RealTimeAPI
dotnet add package Microsoft.AspNetCore.SignalR
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.SqlServer.ServiceBroker

Bu komutlar, SignalR ve Entity Framework Core gibi gerekli kütüphaneleri ASP.NET Core projemize dahil eder.

Adım 2: Veritabanı Kurulumu ve Entity Framework Core Kullanımı
Veritabanı Modeli

Örnek uygulamamızda iki tablo kullanacağız: Personeller ve Satislar. Bu tablolarda personellerin yaptığı satışlar tutulacak ve bu veriler anlık olarak takip edilecektir.

CREATE TABLE Personeller (
    Id INT PRIMARY KEY IDENTITY,
    Ad NVARCHAR(100),
    Soyad NVARCHAR(100)
);

CREATE TABLE Satislar (
    Id INT PRIMARY KEY IDENTITY,
    PersonelId INT,
    Fiyat DECIMAL(18,2),
    FOREIGN KEY (PersonelId) REFERENCES Personeller(Id)
);

Bu iki tablo arasında bir PersonelId ilişkisi bulunuyor ve bu ilişkiyi Entity Framework Core kullanarak yöneteceğiz.

Entity Framework Core Konfigürasyonu

Entity Framework Core’u ASP.NET Core projemizde kullanarak bu tablo yapılarını modele döküyoruz.

public class AppDbContext : DbContext
{
    public DbSet<Personel> Personeller { get; set; }
    public DbSet<Satis> Satislar { get; set; }

    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Satis>()
            .HasOne(s => s.Personel)
            .WithMany(p => p.Satislar)
            .HasForeignKey(s => s.PersonelId);
    }
}

public class Personel
{
    public int Id { get; set; }
    public string Ad { get; set; }
    public string Soyad { get; set; }
    public ICollection<Satis> Satislar { get; set; }
}

public class Satis
{
    public int Id { get; set; }
    public int PersonelId { get; set; }
    public decimal Fiyat { get; set; }
    public Personel Personel { get; set; }
}
Adım 3: SignalR ile Gerçek Zamanlı Haberleşme
SignalR Hub Oluşturma

ASP.NET Core tarafında SignalR ile haberleşmeyi sağlayacak olan bir Hub sınıfı oluşturuyoruz.

public class SatisHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

Bu Hub sınıfı, gelen istekleri tüm bağlı kullanıcılara iletecek bir yapıya sahiptir.

SignalR Middleware Ayarları

SignalR middleware’ini uygulamaya eklemek için Startup.cs dosyasına aşağıdaki kodları ekliyoruz:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<AppDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddSignalR();

    services.AddCors(options => options.AddPolicy("CorsPolicy",
        builder =>
        {
            builder.AllowAnyMethod().AllowAnyHeader()
                   .WithOrigins("http://localhost:4200")
                   .AllowCredentials();
        }));

    services.AddControllers();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseRouting();

    app.UseCors("CorsPolicy");

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapHub<SatisHub>("/satisHub");
    });
}

Bu ayarlar, SignalR’ın Angular frontend ile haberleşmesini sağlamak amacıyla gerekli CORS (Cross-Origin Resource Sharing) politikalarını da içermektedir.

Adım 4: SQL Server Service Broker Kullanımı

Service Broker, SQL Server’da veritabanı değişikliklerini tetiklemek için kullanılan bir servistir. Service Broker’ı etkinleştirmek için aşağıdaki komutu kullanabilirsiniz:

ALTER DATABASE YourDatabaseName SET ENABLE_BROKER;

Service Broker, veri tabanında herhangi bir değişiklik olduğunda bir tetikleyici (trigger) aracılığıyla SignalR Hub’ına bu değişiklikleri bildirecektir.

Adım 5: Gerçek Zamanlı Veri Güncellemeleri
Veritabanı Değişikliklerinin Yakalanması

Veritabanındaki değişiklikleri yakalayabilmek için SqlDependency sınıfını kullanacağız. Bu sınıf, SQL Server’dan veri değişikliklerini dinleyip, SignalR Hub’ına bildirim yapmamızı sağlar.

public class SatisListener
{
    private readonly AppDbContext _context;
    private readonly IHubContext<SatisHub> _hubContext;

    public SatisListener(AppDbContext context, IHubContext<SatisHub> hubContext)
    {
        _context = context;
        _hubContext = hubContext;
    }

    public void Start()
    {
        SqlDependency.Start(_context.Database.GetDbConnection().ConnectionString);

        WatchSatislar();
    }

    private void WatchSatislar()
    {
        using var command = _context.Database.GetDbConnection().CreateCommand();
        command.CommandText = "SELECT Id, Fiyat FROM dbo.Satislar";
        var dependency = new SqlDependency(command);
        dependency.OnChange += async (sender, e) =>
        {
            if (e.Type != SqlNotificationType.Change)
                return;

            var satislar = await _context.Satislar.Include(s => s.Personel).ToListAsync();
            await _hubContext.Clients.All.SendAsync("ReceiveSatisUpdates", satislar);

            WatchSatislar(); // Yeniden izlemeye başla
        };

        command.ExecuteReader();
    }

    public void Stop()
    {
        SqlDependency.Stop(_context.Database.GetDbConnection().ConnectionString);
    }
}
Adım 6: Angular Frontend ile SignalR Entegrasyonu
SignalR ile Bağlantı Kurma

Angular frontend tarafında SignalR’ı kullanarak, arka plandan gelen veri güncellemelerini almak için aşağıdaki gibi bir servis oluşturuyoruz:

import { Injectable } from '@angular/core';
import { HubConnection, HubConnectionBuilder } from '@microsoft/signalr';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class SatisService {
  private hubConnection: HubConnection;
  private satislarSubject = new BehaviorSubject<any[]>([]);
  satislar$ = this.satislarSubject.asObservable();

  constructor() {
    this.hubConnection = new HubConnectionBuilder()
      .withUrl('http://localhost:5000/satisHub')
      .build();

    this.hubConnection.start()
      .catch(err => console.error(err));

    this.hubConnection.on('ReceiveSatisUpdates', (satislar) => {
      this.satislarSubject.next(satislar);
    });
  }
}

Bu servis, SignalR üzerinden gelen veri güncellemelerini yakalar ve bu verileri Angular bileşenlerine aktarır.

Grafiksel Gösterim

Alınan verileri Angular’da grafiksel olarak göstermek için bir kütüphane (örneğin highcharts) kullanabiliriz. Bu kütüphane verileri grafik olarak görselleştirir ve kullanıcıya anlık veri akışını sunar.

import { Component, OnInit } from '@angular/core';
import { SatisService } from './satis.service';
import * as Highcharts from 'highcharts';

@Component({
  selector: 'app-satis-chart',
  template: '<div id="chartContainer"></div>'
})
export class SatisChartComponent implements OnInit {
  Highcharts: typeof Highcharts = Highcharts;
  chartOptions: Highcharts.Options;

  constructor(private satisService: SatisService) {}

  ngOnInit() {
    this.satisService.satislar$.subscribe(satislar => {
      this.updateChart(satislar);
    });
  }

  updateChart(satislar) {
    this.chartOptions = {
      chart: {
        type: 'bar'
      },
      title: {
        text: 'Personel Satışları'
      },
      xAxis: {
        categories: satislar.map(s => s.Personel.Ad)
      },
      yAxis: {
        title: {
          text: 'Satış Miktarı'
        }
      },
      series: [{
        name: 'Satışlar',
        data: satislar.map(s => s.Fiyat)
      }]
    };
    Highcharts.chart('chartContainer', this.chartOptions);
  }
}

SignalR İle Realtime Uygulama Geliştirme

Bu rehberde, SignalR kullanarak dağıtık bir sistemde gerçek zamanlı iletişim sağlayan bir uygulama geliştireceğiz. Bu süreçte RabbitMQ gibi mesaj kuyruk sistemlerini kullanarak, büyük ölçekli ve performanslı uygulamalar nasıl geliştirilebilir, bunu detaylandıracağız.

1. Giriş ve Genel Bilgilendirme

SignalR, ASP.NET Core ile entegre çalışan, tarayıcılar ve sunucu arasında gerçek zamanlı (realtime) iletişimi sağlayan bir kütüphanedir. SignalR, özellikle web tabanlı uygulamalarda kullanıcı deneyimini iyileştirmek için kullanılır. Bu teknoloji, tarayıcıların ve sunucuların birbirleriyle gerçek zamanlı olarak iletişim kurmasını sağlar.

RabbitMQ ise bir mesaj kuyruk sistemidir. Bu tür sistemler, mesajların bir kuyruğa eklenmesini ve bu mesajların sıralı olarak işlenmesini sağlar. RabbitMQ, yüksek performans ve ölçeklenebilirlik gerektiren uygulamalarda yaygın olarak kullanılır.

2. Proje Kurulumu ve Gereksinimler

İlk olarak, Angular frontend ve ASP.NET Core backend olmak üzere iki katmandan oluşan bir proje oluşturacağız. Frontend tarafında Angular kullanılmasının sebebi, SignalR ile entegrasyonun kolaylıkla yapılabilmesi ve kullanıcıya anlık geri bildirimler sunabilmemizdir. Backend tarafında ise ASP.NET Core ile SignalR’ı kullanarak veritabanı değişikliklerini anlık olarak takip edeceğiz.

Angular Uygulaması Oluşturma

Angular uygulamasını oluşturmak için aşağıdaki adımları izleyebilirsiniz:

ng new RealTimeApp
cd RealTimeApp
ng add @aspnet/signalr

Bu komutlarla Angular projemizi oluşturuyoruz ve SignalR için gerekli olan kütüphaneyi projeye dahil ediyoruz.

ASP.NET Core Uygulaması Oluşturma

Aşağıdaki komutları kullanarak ASP.NET Core projemizi oluşturabiliriz:

dotnet new webapi -n RealTimeAPI
cd RealTimeAPI
dotnet add package Microsoft.AspNetCore.SignalR
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.SqlServer.ServiceBroker

Bu komutlar, SignalR ve Entity Framework Core gibi gerekli kütüphaneleri ASP.NET Core projemize dahil eder.

3. SignalR ve RabbitMQ ile Gerçek Zamanlı İşlem

Bu projede, bir RabbitMQ kuyruğu oluşturup, gelen istekleri bu kuyruk üzerinden yöneteceğiz. Böylece, gelen yoğun isteklerin aynı anda işlenmesi yerine, kuyruğa alınarak sıralı bir şekilde işlenmesi sağlanacaktır.

SignalR Hub Oluşturma

SignalR, sunucu tarafında bir Hub sınıfı kullanılarak yönetilir. Hub, istemcilerden gelen mesajları alır ve bu mesajları diğer istemcilere gönderir.

public class MessageHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

Yukarıdaki Hub sınıfı, gelen mesajları tüm bağlı istemcilere yayınlar.

RabbitMQ ile Mesaj Kuyruğu Oluşturma

RabbitMQ kullanarak bir mesaj kuyruğu oluşturmak için aşağıdaki adımları takip edebiliriz:

  1. RabbitMQ Bağlantısı: İlk olarak RabbitMQ’ya bir bağlantı oluşturacağız.
  2. Mesaj Gönderimi: Kuyruğa mesaj gönderilecek.
  3. Mesaj Tüketimi: Kuyruktaki mesajlar tüketilecek.
using RabbitMQ.Client;
using System.Text;

public class RabbitMQService
{
    private readonly IConnection _connection;
    private readonly IModel _channel;

    public RabbitMQService()
    {
        var factory = new ConnectionFactory() { HostName = "localhost" };
        _connection = factory.CreateConnection();
        _channel = _connection.CreateModel();
        
        _channel.QueueDeclare(queue: "task_queue",
                             durable: true,
                             exclusive: false,
                             autoDelete: false,
                             arguments: null);
    }

    public void SendMessage(string message)
    {
        var body = Encoding.UTF8.GetBytes(message);

        var properties = _channel.CreateBasicProperties();
        properties.Persistent = true;

        _channel.BasicPublish(exchange: "",
                             routingKey: "task_queue",
                             basicProperties: properties,
                             body: body);
    }

    public void Close()
    {
        _channel.Close();
        _connection.Close();
    }
}

Yukarıdaki RabbitMQService sınıfı, RabbitMQ’ya bağlanmak ve mesajları kuyruğa göndermek için kullanılır.

RabbitMQ Tüketici Uygulaması (Consumer)

RabbitMQ’da mesajları tüketen bir konsol uygulaması geliştiriyoruz:

using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text;

public class RabbitMQConsumer
{
    public void StartConsumer()
    {
        var factory = new ConnectionFactory() { HostName = "localhost" };
        using var connection = factory.CreateConnection();
        using var channel = connection.CreateModel();
        
        channel.QueueDeclare(queue: "task_queue",
                             durable: true,
                             exclusive: false,
                             autoDelete: false,
                             arguments: null);

        var consumer = new EventingBasicConsumer(channel);
        consumer.Received += (model, ea) =>
        {
            var body = ea.Body.ToArray();
            var message = Encoding.UTF8.GetString(body);
            Console.WriteLine(" [x] Received {0}", message);
        };

        channel.BasicConsume(queue: "task_queue",
                             autoAck: true,
                             consumer: consumer);

        Console.WriteLine(" Press [enter] to exit.");
        Console.ReadLine();
    }
}

Bu kod, RabbitMQ kuyruğundan mesajları alır ve konsolda görüntüler.

4. SignalR ve RabbitMQ Entegrasyonu

SignalR ve RabbitMQ entegrasyonu, istemciden gelen mesajların RabbitMQ kuyruğuna eklenmesini ve daha sonra bu kuyruğun tüketilerek, istemcilere geri bildirim verilmesini sağlar.

Örnek Senaryo: Kullanıcı bir mesaj gönderdiğinde, bu mesaj RabbitMQ kuyruğuna eklenir. Kuyrukta bu mesaj işlendiğinde, tüm bağlı istemcilere mesajın işlendiğine dair bilgi verilir.

RabbitMQ ile SignalR Kullanımı

RabbitMQ’ya eklenen bir mesajın işlendiğinde SignalR Hub üzerinden tüm istemcilere bildirim yapılması için aşağıdaki adımları takip edebiliriz:

public class MessageProcessor
{
    private readonly IHubContext<MessageHub> _hubContext;

    public MessageProcessor(IHubContext<MessageHub> hubContext)
    {
        _hubContext = hubContext;
    }

    public async Task ProcessMessage(string message)
    {
        // Mesaj işleme mantığı burada olacak (örneğin: bir veritabanına kaydetme)
        await _hubContext.Clients.All.SendAsync("ReceiveMessage", "Server", message);
    }
}
5. Angular Uygulamasında SignalR Kullanımı

Angular tarafında SignalR kullanarak anlık güncellemeleri almak için şu adımları izleyebilirsiniz:

import { Injectable } from '@angular/core';
import { HubConnection, HubConnectionBuilder } from '@microsoft/signalr';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class SignalRService {
  private hubConnection: HubConnection;
  private messageSource = new BehaviorSubject<string>("");

  currentMessage = this.messageSource.asObservable();

  constructor() {
    this.hubConnection = new HubConnectionBuilder()
      .withUrl('http://localhost:5000/messageHub')
      .build();

    this.hubConnection.start().catch(err => console.error(err.toString()));

    this.hubConnection.on('ReceiveMessage', (user: string, message: string) => {
      this.messageSource.next(message);
    });
  }
}

Bu servis, SignalR Hub’dan gelen mesajları dinler ve bileşenlere iletir.

Kaynakça

Düşünmeden bir gün bile geçiremediğiniz bir şeyden asla vazgeçmeyin.

Winston Churchill

Bir sonraki yazıda görüşmek dileğiyle!”

Leave a Reply

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir


10 + 2 = ?