Node.js İle Socket.io Kullanarak Canlı Çevrimiçi Satranç Oyunu Nasıl Yapılır?

Node.js İle Socket.io Kullanarak Canlı Çevrimiçi Satranç Oyunu Nasıl Yapılır?
Node.js İle Socket.io Kullanarak Canlı Çevrimiçi Satranç Oyunu Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Projeye başlamadan önce sisteminizde Node.js'in güncel bir LTS (Long Term Support) sürümünün yüklü olduğundan emin olun. 2026 yılı standartlarına göre Node.js 22+ sürümünü kullanmanızı öneririm. Ayrıca temel düzeyde JavaScript (ES6+), Express.js ve Socket.io kütüphanesi bilgisi gereklidir.

  • Node.js (v22 veya üzeri)
  • npm veya pnpm paket yöneticisi
  • chess.js (Satranç kurallarını yönetmek için)
  • socket.io (İstemci-Sunucu iletişimi için)

Proje dizininizi oluşturun ve gerekli bağımlılıkları yüklemek için terminalde şu komutları çalıştırın:

mkdir satranc-oyunu
cd satranc-oyunu
npm init -y
npm install express socket.io chess.js

Sunucu Tarafında Temel Yapılandırma

Sunucu tarafında Express.js ile bir HTTP sunucusu oluşturup, bunu Socket.io ile entegre etmemiz gerekiyor. Socket.io, WebSocket protokolünü temel alır ancak bağlantı koptuğunda otomatik yeniden bağlanma gibi özelliklerle geliştiriciye kolaylık sağlar.

const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const { Chess } = require('chess.js');

const app = express();
const server = http.createServer(app);
const io = new Server(server);

const game = new Chess();

io.on('connection', (socket) => {
    console.log('Bir oyuncu bağlandı:', socket.id);
    
    socket.on('hamle', (move) => {
        try {
            const result = game.move(move);
            if (result) {
                io.emit('hamle_yapildi', game.fen());
            }
        } catch (e) {
            socket.emit('gecersiz_hamle', 'Bu hamle kurallara aykırı!');
        }
    });
});

server.listen(3000, () => console.log('Sunucu 3000 portunda çalışıyor.'));

Yukarıdaki kod bloğunda, chess.js kütüphanesini kullanarak oyunun kurallarını sunucuda doğruluyoruz. Bu, istemci tarafında yapılabilecek olası hileleri engellemek için kritik bir adımdır.

İstemci Tarafında Socket.io Entegrasyonu

İstemci tarafında, kullanıcının hamlelerini sunucuya göndermek ve sunucudan gelen güncel tahta durumunu (FEN - Forsyth-Edwards Notation) yakalamak için Socket.io istemci kütüphanesini kullanacağız. FEN, satranç tahtasının o anki durumunu temsil eden standart bir metin dizisidir.

const socket = io();

function hamleGonder(source, target) {
    socket.emit('hamle', { from: source, to: target });
}

socket.on('hamle_yapildi', (fen) => {
    tahtayiGuncelle(fen);
});

socket.on('gecersiz_hamle', (mesaj) => {
    alert(mesaj);
});

Bu kod bloğu, kullanıcının yaptığı hamleyi sunucuya iletir ve sunucudan gelen onay mesajı ile tahtayı günceller. Kullanıcı arayüzünde herhangi bir kütüphane (React, Vue veya düz JS) kullanabilirsiniz.

Oyun Durumu Yönetimi ve Güvenlik

Satranç oyunlarında en büyük zorluk, hangi oyuncunun hangi renkle oynadığını takip etmektir. Socket.io'nun "room" (oda) özelliğini kullanarak oyuncuları eşleştirmemiz gerekir. Ayrıca, her hamlenin sadece sırası gelen oyuncu tarafından yapılmasını sağlamalıyız.

Kritik Güvenlik Uyarısı: Asla istemciden gelen veriye güvenmeyin. Satranç tahtasının geçerliliğini ve hamle kurallarını mutlaka sunucu tarafında chess.js kullanarak doğrulayın. İstemci sadece bir görüntüleme aracıdır.

Oda mantığı ile oyuncuları gruplandıran örnek yapı:

let oyuncular = {};

io.on('connection', (socket) => {
    if (!oyuncular.beyaz) {
        oyuncular.beyaz = socket.id;
        socket.emit('rol', 'beyaz');
    } else if (!oyuncular.siyah) {
        oyuncular.siyah = socket.id;
        socket.emit('rol', 'siyah');
    }
});

Performans ve Ölçeklenebilirlik Karşılaştırması

Canlı oyun uygulamalarında kullanılan farklı yöntemlerin avantaj ve dezavantajlarını aşağıdaki tabloda görebilirsiniz:

Yöntem Avantajı Dezavantajı
Polling (Düzenli İstek) Basit yapı Yüksek sunucu yükü, gecikme
Socket.io (WebSocket) Anlık iletişim, düşük gecikme Sunucu durum yönetimi gerektirir
WebRTC Sunucusuz P2P iletişim Bağlantı kurulumu karmaşık

Yaygın Hatalar ve Debug İpuçları

Geliştirme sürecinde karşılaşabileceğiniz en yaygın hatalardan biri, "Race Condition" yani yarış durumudur. İki oyuncu aynı anda hamle yapmaya çalıştığında sunucunun durumu karıştırabilir. Bunu önlemek için sunucu tarafında her oyun için ayrı bir Chess nesnesi oluşturduğunuzdan emin olun.

Debug yapmak için Socket.io'nun dahili loglama özelliğini kullanabilirsiniz:

// Sunucu başlatma sırasında logları açın
localStorage.debug = 'socket.io:*';

Sıkça Sorulan Sorular

Socket.io yerine neden doğrudan WebSocket kullanmıyorum?

Socket.io, WebSocket'in üzerine eklenmiş bir katmandır. Bağlantı koptuğunda otomatik yeniden bağlanma, oda desteği ve fallback (eski tarayıcılar için) özellikleri sunar. Satranç gibi kesintisiz bağlantı gerektiren oyunlar için idealdir.

Oyun bittiğini nasıl anlarım?

chess.js kütüphanesindeki game.isGameOver() metodunu kullanarak oyunun mat, pat veya beraberlik durumuna gelip gelmediğini kontrol edebilir ve bu durumu istemcilere bildirebilirsiniz.

Veritabanı kullanmalı mıyım?

Eğer oyuncuların hamle geçmişini kaydetmek veya oyunları sonradan izlenebilir kılmak istiyorsanız, MongoDB veya PostgreSQL gibi bir veritabanı kullanmanız gerekir. Ancak sadece anlık oyun için RAM üzerinde tutmak yeterlidir.

Mobil cihazlarda bağlantı kopmaları nasıl yönetilir?

Socket.io, bağlantı koptuğunda "reconnect" olayını tetikler. Bu olay gerçekleştiğinde, sunucudan mevcut oyunun FEN kodunu tekrar isteyerek tahtayı senkronize edebilirsiniz.

Birden fazla oyun masasını nasıl yönetirim?

Her oyun için benzersiz bir oda ID'si oluşturun ve socket.join(odaID) metodunu kullanarak oyuncuları bu odalara dahil edin.

Oyun Süresi ve Zaman Kontrolü (Chess Clock) Uygulaması

Satranç oyunlarında en kritik özelliklerden biri zaman yönetimidir. Socket.io ile her hamle sonrası sunucu tarafında bir sayaç başlatmak, oyunun adil bir şekilde ilerlemesini sağlar. İstemci tarafında sayaç tutmak güvenlik açığı yaratır; çünkü kullanıcı tarayıcı konsolu üzerinden süreyi manipüle edebilir. Bu nedenle, zamanlayıcıyı tamamen Node.js tarafında yönetmelisiniz.

Aşağıdaki örnek, bir oyun odası için basit bir geri sayım mantığını göstermektedir:


// Sunucu tarafında zamanlayıcı yönetimi
const gameTimers = {};

function startTimer(roomId, duration) {
    let timeLeft = duration;
    gameTimers[roomId] = setInterval(() => {
        timeLeft--;
        io.to(roomId).emit('timerUpdate', { timeLeft });

        if (timeLeft  {
    clearInterval(gameTimers[data.roomId]);
    // Hamle mantığını çalıştır...
    startTimer(data.roomId, 300); // 5 dakika süre
});

Üretim Ortamına (Deployment) Geçiş ve Ölçeklendirme

Uygulamanızı yerel ortamdan canlı sunucuya taşırken, Socket.io'nun doğası gereği dikkat etmeniz gereken bazı kritik noktalar vardır. Özellikle birden fazla sunucu (horizontal scaling) kullanacaksanız, Socket.io bağlantıları farklı sunuculara dağılabilir ve bu da oyuncuların birbirini görememesine neden olur.

Redis Adapter Kullanımı

Birden fazla Node.js örneği çalıştırıyorsanız, @socket.io/redis-adapter kullanarak tüm sunucuların birbirleriyle haberleşmesini sağlamalısınız. Bu sayede bir sunucuya bağlı olan oyuncu, diğer sunucudaki rakibine hamle gönderebilir.


const { createClient } = require('redis');
const { createAdapter } = require('@socket.io/redis-adapter');

const pubClient = createClient({ url: 'redis://localhost:6379' });
const subClient = pubClient.duplicate();

io.adapter(createAdapter(pubClient, subClient));

Güvenlik ve Optimizasyon İpuçları

  • Input Validation: Gelen her hamleyi chess.js gibi bir kütüphane ile sunucu tarafında mutlaka doğrulayın. Kullanıcının gönderdiği hamlenin kurallara uygun olup olmadığını kontrol etmeden tahtayı güncellemeyin.
  • Rate Limiting: Oyuncuların saniyede yüzlerce hamle isteği göndermesini engellemek için express-rate-limit veya Socket.io middleware kullanarak istekleri kısıtlayın.
  • CORS Yapılandırması: Socket.io bağlantılarını sadece kendi domain adresinizden gelecek şekilde kısıtlayın.

// Güvenli bağlantı yapılandırması
const io = require('socket.io')(server, {
    cors: {
        origin: "https://sizinoyununuz.com",
        methods: ["GET", "POST"]
    }
});

Son olarak, oyununuzu yayına alırken PM2 gibi bir süreç yöneticisi kullanarak uygulamanın çökmesi durumunda otomatik olarak yeniden başlatılmasını sağlayın. Bu, canlı satranç deneyiminin kesintisiz sürmesi için hayati önem taşır.

Sonuç

Node.js ve Socket.io kullanarak canlı bir satranç oyunu geliştirmek, gerçek zamanlı sistemlerin mimarisini anlamak için mükemmel bir projedir. Bu rehberde, sunucu tabanlı doğrulama, oda yönetimi ve istemci-sunucu senkronizasyonu konularını ele aldık. Bir sonraki adım olarak, oyuncuların profil bilgilerini tutmak için bir veritabanı ekleyebilir veya oyun süresini kontrol etmek için bir sayaç (timer) mekanizması geliştirebilirsiniz.

Sorumluluk Reddi: Bu makalede paylaşılan kodlar eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce giriş doğrulamalarını (input validation), güvenlik duvarlarını (helmet.js) ve DDoS koruma önlemlerini yapılandırmayı unutmayın.
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