Flutter & Mobil İle İleri Düzey Websocket Gerçek Zamanlı Veri Akışı Nasıl Yapılır?

Flutter & Mobil İle İleri Düzey Websocket Gerçek Zamanlı Veri Akışı Nasıl Yapılır?
Flutter & Mobil İle İleri Düzey Websocket Gerçek Zamanlı Veri Akışı Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Websocket mimarisini Flutter projenize entegre etmeden önce geliştirme ortamınızın güncel olduğundan emin olmalısınız. 2026 yılı itibarıyla Flutter 3.x ve üzeri sürümlerde, null-safety (boş değer güvenliği) standartlarını tam olarak destekleyen kütüphaneler kullanacağız.

  • Flutter SDK (3.24 veya üzeri önerilir)
  • Dart 3.6+ sürümü
  • web_socket_channel paketi (Resmi Flutter topluluk paketi)
  • Backend tarafında bir Websocket sunucusu (Node.js/Socket.io veya Go/Gorilla WebSocket)

Projenizin pubspec.yaml dosyasına gerekli bağımlılığı ekleyerek işe başlayın:

dependencies:
  flutter:
    sdk: flutter
  web_socket_channel: ^3.0.0

Bağımlılığı ekledikten sonra terminalde flutter pub get komutunu çalıştırarak paketleri projenize dahil edin.

Websocket Bağlantısını Kurma ve Yönetme

Websocket bağlantısı kurmak, bir kanal (channel) oluşturmakla başlar. Bağlantının kopması durumunda yeniden bağlanma (reconnection) mekanizması, profesyonel bir uygulamanın olmazsa olmazıdır. Aşağıdaki örnekte, temel bir bağlantı sınıfı oluşturuyoruz.

import 'package:web_socket_channel/web_socket_channel.dart';

class SocketService {
  late WebSocketChannel _channel;

  void connect() {
    _channel = WebSocketChannel.connect(
      Uri.parse('wss://api.uygulamaniz.com/ws'),
    );
  }

  void sendData(String message) {
    _channel.sink.add(message);
  }

  void dispose() {
    _channel.sink.close();
  }
}

Yukarıdaki kod, wss:// protokolünü kullanarak güvenli bir bağlantı başlatır. sink nesnesi, sunucuya veri göndermek için kullanılırken, bağlantı kapatıldığında dispose metodu ile kaynakların serbest bırakılması bellek sızıntılarını önler.

Gerçek Zamanlı Veri Akışını Dinleme (Stream Dinleyicileri)

Sunucudan gelen verileri anlık olarak arayüzde göstermek için StreamBuilder widget'ı en verimli yöntemdir. Bu yöntem, verinin değiştiği her an arayüzün yeniden çizilmesini sağlar.

StreamBuilder(
  stream: _channel.stream,
  builder: (context, snapshot) {
    if (snapshot.hasError) return Text('Hata oluştu');
    if (!snapshot.hasData) return CircularProgressIndicator();
    
    return Text('Gelen Veri: ${snapshot.data}');
  },
)

Bu yapı, gelen her paketi otomatik olarak yakalar. snapshot.hasData kontrolü, bağlantı kurulduktan sonra gelen ilk ve sonraki tüm mesajları işlemek için kullanılır.

Websocket İletişim Yöntemlerinin Karşılaştırılması

Mobil uygulamalarda gerçek zamanlı veri akışı için kullanılan yöntemlerin avantaj ve dezavantajlarını aşağıda görebilirsiniz:

Yöntem Avantaj Dezavantaj
Websocket Çift yönlü, düşük gecikme Sunucu tarafında yüksek kaynak tüketimi
HTTP Polling Basit, her sunucu destekler Yüksek gecikme, gereksiz trafik
gRPC Streaming Verimli, tip güvenli Mobil tarafta kurulumu karmaşık

Güvenli Veri İletişimi ve Kimlik Doğrulama

Websocket bağlantıları, HTTP istekleri gibi standart header'lar taşımaz. Bu nedenle kimlik doğrulama işlemini bağlantı kurulurken (handshake aşamasında) veya bağlantı kurulduktan hemen sonra bir "auth" mesajı göndererek yapmalısınız.

// Bağlantı kurulduktan sonra token ile kimlik doğrulama
void authenticate(String token) {
  _channel.sink.add('{"action": "auth", "token": "$token"}');
}

Güvenlik Uyarısı: Websocket üzerinden asla şifrelenmemiş (plain-text) hassas veri göndermeyin. Her zaman wss:// (Websocket Secure) protokolünü kullanın. Ayrıca, sunucu tarafında gelen mesajları mutlaka doğrulayın (sanitization) ve SQL Injection gibi saldırılara karşı parametreli sorgular kullanın.

İleri Düzey Hata Ayıklama ve Bağlantı İzleme

Gerçek zamanlı uygulamalarda en büyük sorun, bağlantının arka planda sessizce kopmasıdır. Bunu çözmek için "Heartbeat" (kalp atışı) mekanizması kurmalısınız. Belirli aralıklarla sunucuya küçük bir "ping" paketi gönderip "pong" cevabı beklemek, bağlantının canlılığını doğrular.

import 'dart:async';

Timer? _heartbeatTimer;

void startHeartbeat() {
  _heartbeatTimer = Timer.periodic(Duration(seconds: 30), (timer) {
    _channel.sink.add('ping');
  });
}

Bu kod bloğu, bağlantının aktif kalmasını sağlar ve ağ kesintilerini anında tespit etmenize olanak tanır.

Sıkça Sorulan Sorular

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

Genellikle mobil cihazların güç tasarrufu modu veya ağ geçidi (gateway) zaman aşımları nedeniyle bağlantı düşer. Heartbeat mekanizması kullanmak bu sorunu çözer.

JSON verilerini nasıl işlerim?

Gelen string veriyi dart:convert kütüphanesini kullanarak jsonDecode() ile bir Dart nesnesine dönüştürmeniz gerekir.

Websocket ile dosya gönderilebilir mi?

Teknik olarak evet, ancak büyük dosyalar için Websocket yerine HTTP multipart upload yöntemini kullanmanız daha verimlidir.

Sunucu tarafında hangi dili seçmeliyim?

Gerçek zamanlı uygulamalar için Node.js (Socket.io) veya Go (Gorilla) yüksek eşzamanlılık desteği sunduğu için en iyi tercihlerdir.

Bağlantı koparsa otomatik nasıl bağlanırım?

WebSocketChannel nesnesini bir try-catch bloğu içinde sarmalayarak, hata durumunda Future.delayed ile belirli aralıklarla tekrar connect() metodunu çağıran bir döngü kurabilirsiniz.

Sorumluluk Reddi: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce hata yönetimi, yük dengeleme (load balancing) ve veri şifreleme katmanlarını uygulamanızın özel ihtiyaçlarına göre yapılandırmanız gerekmektedir.

Websocket Performans Optimizasyonu ve Veri Serileştirme

Gerçek zamanlı uygulamalarda yüksek frekanslı veri akışı, mobil cihazların pil ömrünü ve işlemci performansını doğrudan etkiler. Özellikle binlerce mesajın saniyeler içinde işlendiği senaryolarda, veriyi işleme biçiminiz uygulamanın akıcılığını belirler.

Veri İşleme Maliyetini Düşürmek

JSON verilerini her seferinde jsonDecode() ile ayrıştırmak, büyük veri paketlerinde ciddi bir CPU yükü oluşturur. Bunun yerine compute fonksiyonunu kullanarak ayrıştırma işlemini ayrı bir izole (isolate) üzerinde gerçekleştirebilirsiniz.

import 'dart:convert';
import 'package:flutter/foundation.dart';

// Veriyi arka planda işlemek için yardımcı fonksiyon
Future parseJsonAsync(String data) async {
  return compute(_decodeAndParse, data);
}

Map _decodeAndParse(String data) {
  return jsonDecode(data);
}

Binary Veri Transferi (Protobuf Kullanımı)

Eğer çok yüksek veri trafiğine sahip bir uygulama geliştiriyorsanız, JSON yerine Protocol Buffers (Protobuf) kullanmak bant genişliğini ve işlemci kullanımını %70'e kadar azaltabilir. Protobuf, veriyi ikili (binary) formatta sıkıştırarak gönderdiği için metin tabanlı JSON'a göre çok daha hızlıdır.

Websocket Üzerinde Birim ve Entegrasyon Testleri

Websocket bağlantılarını test etmek, uygulamanın kararlılığı için kritiktir. Canlı bir sunucuya bağımlı kalmadan test yapabilmek için StreamController kullanarak sahte (mock) bir sunucu ortamı oluşturabilirsiniz.

Mock Sunucu ile Test Senaryosu

Aşağıdaki örnek, gerçek bir ağ bağlantısı kurmadan websocket akışını nasıl simüle edebileceğinizi gösterir:

import 'dart:async';
import 'package:test/test.dart';

void main() {
  test('Websocket mesajı doğru işleniyor mu?', () async {
    final controller = StreamController();
    
    // Test verisini akışa ekle
    controller.add('{"status": "success", "data": 100}');
    
    final stream = controller.stream;
    
    // Akıştan gelen ilk veriyi doğrula
    expect(await stream.first, contains('success'));
    
    await controller.close();
  });
}

Test Stratejileri

  • Bağlantı Kopma Testi: Sunucuyu manuel olarak kapatıp, uygulamanın tekrar bağlanma (reconnect) mantığının devreye girip girmediğini test edin.
  • Paket Kaybı Simülasyonu: Ağ hızını kısıtlayarak (throttling) uygulamanın yüksek gecikme sürelerinde nasıl tepki verdiğini gözlemleyin.
  • State Doğrulama: Websocket üzerinden gelen verinin, uygulama içindeki State (Bloc/Riverpod) yapısını doğru güncellediğinden emin olun.

İleri Düzey İpuçları: Heartbeat ve Keep-Alive

Birçok yük dengeleyici (load balancer), belirli bir süre veri akışı olmayan websocket bağlantılarını "ölü" kabul ederek sonlandırır. Bunu engellemek için sunucu ve istemci arasında periyodik olarak küçük "ping" paketleri göndermek en sağlıklı yöntemdir.

import 'dart:async';

void startHeartbeat(Function sendPing) {
  // Her 30 saniyede bir ping göndererek bağlantıyı canlı tut
  Timer.periodic(Duration(seconds: 30), (timer) {
    sendPing('ping');
  });
}

Bu mekanizma, özellikle mobil cihazların arka plana atıldığı veya ağ geçişlerinin (Wi-Fi'dan 4G'ye geçiş gibi) yaşandığı durumlarda bağlantının kopmadan devam etmesini sağlar.

Sonuç

Flutter ile Websocket entegrasyonu, modern mobil uygulamaların temel taşıdır. Bu rehberde; bağlantı kurma, stream yönetimi, güvenlik önlemleri ve bağlantı sürekliliği sağlayan kalp atışı mekanizmasını ele aldık. Bir sonraki adım olarak, uygulamanızda gelen verileri Bloc veya Riverpod gibi state management kütüphaneleriyle birleştirerek, veri akışını uygulama genelinde yönetmeyi deneyebilirsiniz.

Bu yazıya tepkinizi paylaşın:
Kerem Aydın

Mutfağından bahçesine, yaşamın her alanında hızlı ve etkili çözüm rehberleri hazırlıyorum. Bilgi kirliliğinden uzak, doğrudan sonuca odaklanan içerikler üretiyorum.

Yorumlar (0)

Yorum Yaz