Gereksinimler ve Ön Hazırlık
Bu projeye başlamadan önce bilgisayarınızda Node.js'in güncel bir sürümünün (en az v20.x veya v22.x LTS) kurulu olması gerekir. Ayrıca paket yönetimi için npm veya pnpm kullanacağız.
- Node.js (LTS sürümü önerilir)
- Bir kod editörü (VS Code tavsiye edilir)
- Temel JavaScript (ES6+) bilgisi
- Terminal veya komut satırı kullanımı
Projeyi başlatmak için bir klasör oluşturun ve gerekli kütüphaneleri yükleyin. Biz bu eğitimde en popüler ve performanslı kütüphanelerden biri olan ws kütüphanesini kullanacağız.
mkdir websocket-projesi
cd websocket-projesi
npm init -y
npm install ws
Yukarıdaki komutlar, projenizi başlatır ve Websocket iletişimini sağlayacak olan ws modülünü node_modules klasörüne ekler.
Adım Adım Websocket Sunucusu Kurulumu
Websocket sunucusu, istemcilerden gelen bağlantıları dinleyen ve bu bağlantılar üzerinden veri gönderip alan bir yapıdır. İlk adımda, basit bir sunucu ayağa kaldıracağız.
const { WebSocketServer } = require('ws');
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', (ws) => {
console.log('Yeni bir istemci bağlandı.');
ws.on('message', (data) => {
console.log('Alınan veri: %s', data);
ws.send('Mesajınız sunucuya ulaştı: ' + data);
});
});
console.log('Websocket sunucusu 8080 portunda çalışıyor.');
Bu kodda WebSocketServer sınıfını kullanarak 8080 portunda bir dinleyici oluşturduk. connection olayı, her yeni istemci bağlandığında tetiklenir. message olayı ise istemciden gelen verileri yakalamamızı sağlar.
İstemci Tarafında Bağlantı Nasıl Yapılır?
Sunucumuz hazır olduğuna göre, şimdi tarayıcı üzerinden bu sunucuya bağlanacak bir istemci oluşturalım. Tarayıcılar, yerel olarak WebSocket nesnesini destekler.
const socket = new WebSocket('ws://localhost:8080');
socket.onopen = () => {
console.log('Sunucuya bağlandı!');
socket.send('Merhaba Sunucu!');
};
socket.onmessage = (event) => {
console.log('Sunucudan gelen: ', event.data);
};
Bu kod bloğu, tarayıcı konsolunda çalıştırıldığında sunucuya bir bağlantı isteği gönderir. Bağlantı açıldığında onopen tetiklenir ve sunucuya bir mesaj gönderilir. Sunucudan gelen yanıt ise onmessage ile yakalanır.
Veri Akışı Yönetimi ve Yayınlama (Broadcasting)
Gerçek dünya uygulamalarında, bir istemciden gelen verinin diğer tüm bağlı istemcilere gönderilmesi gerekebilir. Buna "broadcast" veya yayınlama denir.
wss.on('connection', (ws) => {
ws.on('message', (data) => {
wss.clients.forEach((client) => {
if (client.readyState === 1) { // 1: OPEN durumu
client.send(data.toString());
}
});
});
});
Burada wss.clients dizisi üzerinden tüm bağlı istemcileri döngüye alıyoruz. readyState kontrolü, istemcinin hala bağlı olup olmadığını doğrulamak için kritik bir güvenlik ve performans önlemidir.
Websocket İletişim Yöntemlerinin Karşılaştırılması
Websocket dışında veri akışı için kullanılan diğer yöntemlerle bir kıyaslama yapalım:
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Websocket | Çift yönlü, çok hızlı | Bağlantı yönetimi karmaşık |
| Polling | Basit, HTTP tabanlı | Sunucuya sürekli yük bindirir |
| Server-Sent Events | Tek yönlü, kolay | Sadece sunucudan istemciye |
Güvenlik ve Üretim Ortamı İpuçları
Kritik Uyarı: Websocket bağlantılarında XSS (Cross-Site Scripting) saldırılarına karşı gelen veriyi her zaman doğrulayın ve temizleyin. Ayrıca, üretim ortamında (production) mutlaka
wss://(SSL/TLS) protokolünü kullanın. Ham veriyi asla doğrudan veritabanına veya HTML içine yerleştirmeyin.
Bağlantıların güvenliğini sağlamak için verifyClient özelliğini kullanarak bağlantı isteği sırasında kimlik doğrulama yapabilirsiniz.
const wss = new WebSocketServer({
port: 8080,
verifyClient: (info, cb) => {
const token = info.req.headers['sec-websocket-protocol'];
if (token === 'gizli-anahtar') {
cb(true);
} else {
cb(false, 401, 'Unauthorized');
}
}
});
Hata Yönetimi ve Debug İpuçları
Websocket uygulamalarında en sık karşılaşılan sorun bağlantı kopmalarıdır. Bağlantının koptuğunu anlamak için heartbeat (kalp atışı) mekanizması kurmalısınız.
function heartbeat() {
this.isAlive = true;
}
wss.on('connection', (ws) => {
ws.isAlive = true;
ws.on('pong', heartbeat);
});
setInterval(() => {
wss.clients.forEach((ws) => {
if (ws.isAlive === false) return ws.terminate();
ws.isAlive = false;
ws.ping();
});
}, 30000);
Bu yapı, her 30 saniyede bir istemcilere "ping" atar. Yanıt gelmeyen bağlantıları terminate() ile sonlandırarak sunucu kaynaklarını koruruz.
Sıkça Sorulan Sorular
Websocket bağlantısı neden sürekli kopuyor?
Genellikle yük dengeleyiciler (load balancer) veya proxy sunucuları, boşta kalan TCP bağlantılarını kapatır. Yukarıda gösterilen "heartbeat" mekanizmasını kullanarak bağlantıyı canlı tutabilirsiniz.
Websocket ile dosya gönderilebilir mi?
Evet, ancak veriyi Buffer veya Blob formatına çevirmeniz gerekir. Büyük dosyalar için doğrudan Websocket yerine HTTP üzerinden yükleme yapıp, Websocket ile sadece dosya yolunu göndermek daha performanslıdır.
Aynı anda kaç bağlantı destekler?
Node.js'in tek iş parçacıklı yapısı göz önüne alındığında, donanımınıza bağlı olarak binlerce eşzamanlı bağlantıyı yönetebilirsiniz. Ancak mesaj trafiği arttıkça CPU kullanımı artacaktır.
Websocket güvenli mi?
HTTPS/WSS kullanıldığı sürece veriler şifrelenir. Ancak gelen verinin içeriği her zaman doğrulanmalıdır (Input Validation).
Socket.io kullanmalı mıyım?
Eğer otomatik yeniden bağlanma, oda (room) yapısı ve geniş çaplı tarayıcı desteği istiyorsanız Socket.io kullanmak işinizi kolaylaştırır. Ancak saf performans ve düşük bağımlılık istiyorsanız ws kütüphanesi daha uygundur.
Websocket Sunucularını Ölçeklendirme: Redis Pub/Sub Entegrasyonu
Tek bir sunucu üzerinde çalışan Websocket uygulamaları, kullanıcı sayısı arttıkça darboğaz yaşamaya başlar. Node.js tek iş parçacıklı (single-threaded) yapısı gereği CPU yoğun işlemlerde kısıtlı kalabilir. Çoklu sunucu (multi-instance) mimarisine geçtiğinizde, bir sunucuya bağlı olan istemcinin diğer sunucuya bağlı olan istemciye mesaj göndermesi imkansız hale gelir. Bu sorunu çözmek için Redis Pub/Sub mekanizması kullanılır.
Redis, sunucular arasında bir "mesaj otobüsü" görevi görür. Bir sunucuya gelen mesaj, Redis'e yayınlanır (publish) ve diğer tüm sunucular bu mesajı dinleyerek (subscribe) kendi bağlı oldukları istemcilere iletir.
// Redis ile mesaj yayınlama örneği
const redis = require('redis');
const publisher = redis.createClient();
function broadcastToAllServers(message) {
publisher.publish('ws_channel', JSON.stringify(message));
}
// Tüm sunucularda çalışan dinleyici
const subscriber = redis.createClient();
subscriber.subscribe('ws_channel');
subscriber.on('message', (channel, message) => {
const data = JSON.parse(message);
// Tüm bağlı istemcilere veriyi gönder
wss.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify(data));
}
});
});
Websocket Performansını İzleme ve Optimizasyon
Gerçek zamanlı uygulamalarda gecikme (latency) en büyük düşmandır. Websocket bağlantılarınızın sağlığını takip etmek için bazı metrikleri izlemeniz gerekir. Özellikle "Heartbeat" mekanizması, bağlantıların canlı kalmasını sağlarken gereksiz kaynak tüketimini de engeller.
Bağlantı Sağlığını İzleme
Bağlantıların kopup kopmadığını anlamak için periyodik olarak "ping" paketleri gönderilmelidir. Eğer istemci belirli bir süre içinde "pong" yanıtı dönmezse, bağlantı sonlandırılmalıdır.
// Sunucu tarafında basit bir heartbeat kontrolü
function heartbeat() {
this.isAlive = true;
}
wss.on('connection', (ws) => {
ws.isAlive = true;
ws.on('pong', heartbeat);
});
const interval = setInterval(() => {
wss.clients.forEach((ws) => {
if (ws.isAlive === false) return ws.terminate();
ws.isAlive = false;
ws.ping();
});
}, 30000); // 30 saniyede bir kontrol et
Performans İpuçları
- Veri Sıkıştırma: Çok büyük JSON verileri gönderiyorsanız,
perMessageDeflateözelliğini kullanarak ağ trafiğini azaltabilirsiniz. - Binary Veri Kullanımı: Mümkünse metin (JSON) yerine
BufferveyaArrayBufferkullanarak veri boyutunu küçültün. - Olay Döngüsünü Korumak: Websocket mesaj işleyicilerinde ağır senkron işlemler (dosya okuma, karmaşık döngüler) yapmaktan kaçının; bu, tüm sunucunun yanıt vermesini durdurabilir.
- Yük Dengeleyici (Load Balancer) Yapılandırması: Nginx veya HAProxy kullanırken
Upgradebaşlıklarının düzgün iletildiğinden ve "sticky session" (oturum sürekliliği) ayarlarının aktif olduğundan emin olun.
Bu optimizasyonlar, uygulamanızın binlerce eşzamanlı bağlantıyı düşük gecikme süresiyle yönetmesine olanak tanır. Özellikle yüksek trafikli canlı sohbet veya borsa verisi uygulamalarında bu mimari standart kabul edilir.
Sonuç
Node.js ile Websocket kullanarak gerçek zamanlı veri akışı sağlamak, doğru kütüphane ve güvenlik önlemleriyle oldukça güçlü bir araçtır. Bu rehberde temel sunucu kurulumundan, veri yayınlamaya ve bağlantı güvenliğine kadar kritik adımları tamamladınız. Bir sonraki adım olarak, Redis kullanarak bu Websocket sunucusunu ölçeklenebilir (scalable) hale getirmeyi veya Socket.io kütüphanesini inceleyerek daha karmaşık oda yapılarını öğrenmeyi deneyebilirsiniz.
Yasal Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamında kullanmadan önce güvenlik açıklarını (SQL injection, XSS vb.) göz önünde bulundurarak profesyonel güvenlik testlerinden geçirmeniz önerilir.


Yorumlar (0)
Yorum Yaz