C# İle Websocket Tabanlı Anlık Bildirim Sistemi Nasıl Yapılır?

C# İle Websocket Tabanlı Anlık Bildirim Sistemi Nasıl Yapılır?
C# İle Websocket Tabanlı Anlık Bildirim Sistemi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Bu uygulamayı geliştirmek için güncel .NET SDK sürümlerini kullanmanız önerilir. 2026 yılı standartları gereği, performans ve güvenlik iyileştirmeleri için en az .NET 8 veya .NET 9 sürümüne sahip olmalısınız. Aşağıdaki araçların sisteminizde kurulu olduğundan emin olun:

  • Visual Studio 2022 veya VS Code (C# Dev Kit eklentisi ile).
  • .NET 9.0 SDK.
  • Tarayıcı üzerinde WebSocket testleri için Postman veya tarayıcı geliştirici araçları (Network sekmesi).

Projenizi oluşturmak için terminal üzerinden dotnet new web -n WebSocketNotificationApp komutunu kullanabilirsiniz. Bu komut, minimal bir ASP.NET Core yapısı oluşturacaktır.

WebSocket Bağlantısını Sunucuda Aktif Etme

ASP.NET Core içerisinde WebSocket desteği varsayılan olarak kapalıdır. Uygulamanızın gelen WebSocket isteklerini kabul edebilmesi için Program.cs dosyasında gerekli middleware (ara yazılım) yapılandırmasını yapmalısınız. Bu işlem, HTTP isteklerinin WebSocket protokolüne yükseltilmesine olanak tanır.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

var webSocketOptions = new WebSocketOptions
{
    KeepAliveInterval = TimeSpan.FromMinutes(2)
};

app.UseWebSockets(webSocketOptions);

app.Run();

Burada UseWebSockets metodu, uygulamanın gelen WebSocket handshake (el sıkışma) isteklerini dinlemesini sağlar. KeepAliveInterval ise bağlantının kopmaması için sunucunun istemciye düzenli olarak ping gönderme süresini belirler.

WebSocket İsteklerini İşleyen Middleware Yazımı

Bağlantıyı kabul ettikten sonra, gelen istekleri yönetmek için özel bir endpoint tanımlamanız gerekir. Bu endpoint, istemci ile kurulan bağlantıyı bir WebSocket nesnesi üzerinden yönetir. Aşağıdaki örnekte, gelen veriyi dinleyen ve istemciye "Bağlantı başarılı" mesajı gönderen bir yapı kuruyoruz.

app.Use(async (context, next) =>
{
    if (context.Request.Path == "/ws")
    {
        if (context.WebSockets.IsWebSocketRequest)
        {
            using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
            await HandleWebSocketConnection(webSocket);
        }
        else
        {
            context.Response.StatusCode = StatusCodes.Status400BadRequest;
        }
    }
    else
    {
        await next();
    }
});

Bu kod bloğu, /ws yoluna gelen istekleri yakalar. Eğer istek bir WebSocket isteği ise AcceptWebSocketAsync ile bağlantıyı kabul eder ve HandleWebSocketConnection metoduna yönlendirir.

İstemciden Gelen Mesajları Okuma ve Yanıtlama

Bağlantı kurulduktan sonra istemciden gelen mesajları sürekli bir döngü içerisinde dinlemelisiniz. ReceiveAsync metodu, mesaj gelene kadar işlemi bekletir. Gelen veriyi işledikten sonra SendAsync ile istemciye yanıt dönebilirsiniz.

async Task HandleWebSocketConnection(WebSocket webSocket)
{
    var buffer = new byte[1024 * 4];
    while (webSocket.State == WebSocketState.Open)
    {
        var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None);
        
        if (result.MessageType == WebSocketMessageType.Text)
        {
            var message = System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count);
            // Gelen mesajı işle
            var response = $"Sunucuya ulaştı: {message}";
            var responseBytes = System.Text.Encoding.UTF8.GetBytes(response);
            await webSocket.SendAsync(new ArraySegment(responseBytes), WebSocketMessageType.Text, true, CancellationToken.None);
        }
    }
}

Bu yapı, bağlantı açık olduğu sürece çalışır. İstemci bağlantıyı sonlandırdığında veya hata oluştuğunda döngüden çıkılır.

Gerçek Zamanlı Bildirim Yönetimi İçin İstemci Tarafı

Sunucu tarafı hazır olduğuna göre, tarayıcı üzerinden bu bağlantıyı nasıl test edeceğinizi bilmelisiniz. JavaScript'in yerleşik WebSocket nesnesi, C# sunucumuzla iletişim kurmak için yeterlidir.

const socket = new WebSocket('ws://localhost:5000/ws');

socket.onopen = () => console.log('Bağlantı kuruldu.');
socket.onmessage = (event) => console.log('Sunucudan gelen:', event.data);
socket.send('Merhaba Sunucu!');

Bu JavaScript kodu, sunucuya bağlanır ve gelen mesajları konsola yazdırır. Tarayıcı konsolunu açarak anlık iletişimi gözlemleyebilirsiniz.

WebSocket ve Alternatiflerin Karşılaştırması

Gerçek zamanlı veri iletimi için sadece WebSocket değil, farklı yöntemler de mevcuttur. İhtiyacınıza en uygun olanı seçmek için aşağıdaki tabloyu inceleyebilirsiniz.

Yöntem Avantajı Dezavantajı
WebSocket Düşük gecikme, çift yönlü Sunucu yükü yüksek olabilir
SignalR Otomatik fallback, kolay kullanım Ek kütüphane bağımlılığı
Server-Sent Events Tek yönlü, basit HTTP İstemciden sunucuya veri gönderemez
Güvenlik Uyarısı: WebSocket bağlantılarında Cross-Site WebSocket Hijacking (CSWSH) saldırılarına karşı dikkatli olunmalıdır. Üretim ortamında (production) mutlaka Origin header kontrolü yapın ve HTTPS (WSS) protokolünü zorunlu kılın. Kullanıcı girdilerini asla doğrudan işlemeden veritabanına veya istemciye göndermeyin, XSS saldırılarına karşı filtreleme yapın.

Sıkça Sorulan Sorular

WebSocket bağlantısı neden sürekli kopuyor?

Bağlantı kopmaları genellikle ağ kesintileri veya sunucunun KeepAlive ayarlarının istemci ile uyumsuz olmasından kaynaklanır. Sunucu tarafında KeepAliveInterval değerini kontrol edin.

Birden fazla kullanıcıya aynı anda nasıl bildirim gönderirim?

Bunun için aktif olan tüm WebSocket nesnelerini bir ConcurrentDictionary koleksiyonunda tutmalı ve bildirim göndermeniz gerektiğinde bu koleksiyon üzerinde dönerek mesajı iletmelisiniz.

WebSocket ile SignalR arasındaki fark nedir?

SignalR, WebSocket protokolünü temel alan ancak bağlantı koptuğunda otomatik olarak Long Polling gibi yöntemlere geri dönen bir soyutlama katmanıdır. WebSocket ise ham protokoldür; tüm hata yönetimi ve bağlantı takibi size aittir.

WebSocket güvenli mi?

WebSocket tek başına şifreli değildir. Mutlaka WSS (WebSocket Secure) kullanarak trafiği TLS ile şifrelemelisiniz. Ayrıca kimlik doğrulama (authentication) için bağlantı kurulmadan önce JWT (JSON Web Token) kullanılması önerilir.

WebSocket ölçeklenebilir mi?

Evet, ancak çok sayıda bağlantı için Redis gibi bir Pub/Sub (yayınla/abone ol) mekanizması kullanarak sunucular arası mesajlaşmayı yönetmeniz gerekir.

WebSocket Uygulamalarında Performans Optimizasyonu

WebSocket bağlantıları, HTTP isteklerine göre çok daha düşük gecikme süresi sunsa da, yüksek trafikli uygulamalarda kaynak yönetimi kritik bir hal alır. Sunucu tarafında binlerce açık bağlantıyı yönetirken bellek tüketimini minimize etmek ve CPU kullanımını optimize etmek için şu stratejileri izlemelisiniz:

  • Bağlantı Havuzu Yönetimi: Bağlantıları bir ConcurrentDictionary içerisinde tutarak thread-safe bir erişim sağlayın.
  • Buffer Boyutlandırma: Mesajları okurken kullanılan buffer boyutunu, uygulamanızın ortalama mesaj boyutuna göre optimize edin. Gereğinden büyük bufferlar bellek sızıntısına yol açabilir.
  • Ping/Pong Mekanizması: Bağlantının canlı kalıp kalmadığını kontrol etmek için düzenli aralıklarla "Heartbeat" (kalp atışı) sinyalleri gönderin.
// Sunucu tarafında bağlantı canlılığını koruma örneği
private async Task KeepAlive(WebSocket webSocket, CancellationToken ct)
{
    var buffer = new byte[1024 * 4];
    while (webSocket.State == WebSocketState.Open && !ct.IsCancellationRequested)
    {
        // 30 saniyede bir ping gönder
        await Task.Delay(30000, ct);
        if (webSocket.State == WebSocketState.Open)
        {
            await webSocket.SendAsync(new ArraySegment(new byte[] { 0x9 }), 
                WebSocketMessageType.Binary, true, ct);
        }
    }
}

WebSocket Hata Ayıklama ve İzleme (Monitoring)

WebSocket trafiği sürekli akış halinde olduğu için geleneksel HTTP hata ayıklama yöntemleri yetersiz kalabilir. Uygulamanızın canlı ortamda nasıl davrandığını anlamak için şu araçları ve yöntemleri kullanabilirsiniz:

1. Tarayıcı Geliştirici Araçları

Chrome veya Edge tarayıcılarında "Network" sekmesine giderek "WS" filtresini seçin. Burada "Messages" sekmesi üzerinden sunucu ile istemci arasında gidip gelen tüm ham veriyi (frame) anlık olarak görebilirsiniz.

2. Logging (Günlükleme)

WebSocket middleware katmanında, bağlantı açılışlarını, kapanışlarını ve oluşan hataları mutlaka yapılandırılmış bir loglama kütüphanesi (Serilog gibi) ile kaydedin. Özellikle WebSocketException hatalarını yakalamak, bağlantı kopmalarının kök nedenini bulmanızı sağlar.

// Hata yakalama ve loglama örneği
try 
{
    await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None);
}
catch (WebSocketException ex)
{
    _logger.LogError($"WebSocket hatası: {ex.WebSocketErrorCode}, Detay: {ex.Message}");
    // Bağlantı koptuğunda temizlik işlemlerini yap
    await webSocket.CloseAsync(WebSocketCloseStatus.InternalServerError, "Hata oluştu", CancellationToken.None);
}

3. Yük Testi

Uygulamanızın aynı anda kaç bağlantıyı kaldırabileceğini test etmek için Artillery veya JMeter gibi araçlar kullanın. Özellikle ws protokolü için yazılmış eklentilerle, binlerce eşzamanlı istemciyi simüle ederek sunucunuzun "Memory Pressure" durumunu gözlemleyin.

Metrik İdeal Değer Kritik Eşik
Bağlantı Gecikmesi < 50ms > 500ms
Bellek Kullanımı Bağlantı başına ~10-20KB > 100KB
Mesaj Kaybı %0 > %1

Sonuç

C# ile WebSocket tabanlı bir anlık bildirim sistemi kurmak, uygulamanızın etkileşim kapasitesini ciddi oranda artırır. Bu rehberde, ham WebSocket protokolü ile bağlantı kurmayı, veri iletmeyi ve temel güvenlik prensiplerini ele aldık. Bir sonraki adım olarak, bu yapıyı bir veritabanı ile entegre ederek "kullanıcı bazlı bildirim" sistemine dönüştürebilir veya SignalR kütüphanesini inceleyerek daha karmaşık senaryoları yönetmeyi deneyebilirsiniz.

Bu yazıya tepkinizi paylaşın:
Deniz Arslan

On yıldır dijital içerik üretimi ve editörlük alanında çalışıyorum. Karmaşık süreçleri herkesin anlayabileceği basit ve adım adım rehberlere dönüştürme konusunda uzmanım.

Yorumlar (0)

Yorum Yaz