Node.js ve Socket.io ile Haber Akışı

 bcakir
 9 Şubat 2014

Yazımızın konusu, Node.js ve Socket.io ile Facebook tarzı haber akışı yapma. Önceki yazımızda gerçek zamanlı uygulamalar hakkında bilgi vermiştim. Ayrıca kullanacağımız teknolojilerin (Node.js ve Socket.io) ne olduğunu ve işlevlerini anlatmıştım. Yapacağımız uygulama basit bir protatip olacak, bu uygulamayı geliştirmek ve farklı amaçlar için kullanmak sizlere kalıyor. Örneğin, sohbet odası (chat room) şeklinde de kullanabilirsiniz. Yapacağımız uygulamada mysql ve socket.io modüllerini kullanacağız (npm paket yöneticisiyle kurmayı unutmayın). Ama uygulamayı geliştirmek ve güvenlik önlemlerini de uygulamaya eklemek isterseniz xss ve felixge modüllerini de kullanmanızı öneririm. Uygulamamızın bir server (server.js) bir de client dosyası (newsfeed.html) olacak. Sunucu tarafını Node.js ile istemci tarafını ise Html ve JQuery ile yapacağız. Bunun yanında yayın yapacağımız port 8000 olacak.

var mysql = require('mysql');
var io = require('socket.io').listen(8000);
var db = mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: '',
    database: 'haberlerDb'
});

db.connect(function(err){
    if(err) console.log(err);
});

var notes = [];
var haberKontrol = false;
var kullaniciSayisi = 0;

io.sockets.on('connection', function(socket){
    kullaniciSayisi++;
    io.sockets.emit('yeniKullanici', kullaniciSayisi);

    socket.on('disconnect', function(){
        kullaniciSayisi--;
        io.sockets.emit('yeniKullanici', kullaniciSayisi);
    });

    socket.on('yeniHaber', function(data){
        io.sockets.emit('yeniHaber', {note: data.note});
        notes.unshift(data);
        db.query('INSERT INTO haberler (icerik) VALUES (?)', data.note);
    });

    if(!haberKontrol){
        db.query('SELECT icerik FROM haberler ORDER BY id DESC LIMIT 10')
            .on('result', function(data){
                notes.push(data);
            })
            .on('end', function(){
                socket.emit('eskiHaberler', notes);
            });

        haberKontrol = true;
    }else{
        socket.emit('eskiHaberler', notes);
    }

});

Sunucu tarafını (server.js) yukarıda oluşturduk. Kısaca ne yaptığımızdan bahsedecek olursak; ilk giren kullanıcı için veritabanından haberleri alıp diziye aktardık ve ekranda yazdırma isteği gönderdik. Yeni haber eklendiğinde ise veritabanına kaydedip dizimize ekledik çünkü dizimizi başka giren kullanıcılara da göstereceğiz. Avantajı, yeni giren kişiler için veritabanından haberleri almak için istekte bulunmayacak olmamız (bu sunucu yükünü çok önemli oranda azaltacaktır). Bu arada önemli bir nokta, dizinin boyutunu sınırlandırmadım, siz belirli bir büyüklükle sınırlayın çünkü hem 1000 tane haberi ekranda göstermeyeceksiniz hem de dizide bulunan veri çok büyüdüğünde bellek hatası alırsınız.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
	<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
	<meta name="author" content="bcakir" />
	<title>Node.js ve Socket.io ile Haber Akışı</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="http://localhost:8000/socket.io/socket.io.js"></script>
<script type="text/javascript">
var socket = io.connect('http://localhost:8000');
$(document).ready(function(){

    socket.on('eskiHaberler', function(data){
        var html = '';
        for (var i = 0; i < data.length; i++){
            html += '<li>' + data[i].icerik + '</li>';
        }
        $('#haberler').html(html);
    });

    socket.on('yeniHaber', function(data){
        $('#haberler').prepend('<li>' + data.note + '</li>');
    });

    socket.on('yeniKullanici', function(data){
        $('#loggin').html('Kullanıcı Sayısı: ' + data);
    });

});

function formKontrol(){
    var icerik = $("#icerik").val();
    if(icerik != ''){
        socket.emit('yeniHaber', {note: icerik});
        $("#icerik").val('');
    }else{
        alert('İçerik alanını boş bırakmayın.');
        return false;
    }
}
</script>

<style type="text/css">
    form div {width: 400px}
    textarea {width: 394px; height: 80px; margin: 0; padding: 3px; resize: vertical;}
    input[type="submit"] {float: right; margin: 3px 0; padding: 7px 15px;}
</style>
</head>
<body>

<ul id="haberler"></ul>
<div id="loggin"></div>

<form action="javascript:formKontrol();">
    <div><textarea id="icerik" name="icerik" placeholder="İçerik giriniz..."></textarea></div>
    <div><input type="submit" name="btnEkle" value="Ekle" /></div>
</form>

</body>
</html>

Yukarıda bulunan kısımda ise istemci tarafını (newsfeed.html) geliştirdik. Sunucudan gönderilen haberleri ekranda gösterdik ve formdan yeni haber girildiğinde, sunucuya yeni kayıt eklenme isteği (database insertion callback) gönderdik. Bu istek sonucunda, haber akışını görüntüleyen kişilerde yeni haberin eklenme işlemi yapıldı. Uygulama içeriğinin anlatımıyla yazımızın sonuna gelmiş bulunuyoruz, ölçeklenebilir (scalable) ve gerçek zamanlı (real-time) uygulamalar için Node.js kategorisini takipte kalın.

 3.384 Okunma

Bu yazıya 10 yorum yapılmış.

  1. Teşekkür ederim gerçekten, tam öğrenmek istediğim konuydu. Baya da kolaymış gerçek zamanlı uygulama geliştirmek.

  2. Facebook node.js mi kullanıyor? Node,js yeni sayılır ama haber akışı ve chat kısmı daha uzun zaman önce vardı. Başka bir teknoloji kullanıyorlar diye düşünüyorum, bunu bizle paylaşabilirseniz bizim de bilgimiz olur.

    • XMPP eski adıyla Jabber kullandıklarını duymuştum. Şimdi aradım Google’da “This document describes the features and limitations of Facebook Chat’s XMPP protocol for the developer who intends to implement a Facebook Chat client.” diyor, yani dediğim gibi XMPP’imiş.

  3. html dosyasının 16. satırına database’de ki field’ın adı gelmeli

    html += ” + data[i].icerik + ”;

    • Veritabanı yapısı daha kolay anlaşılsın diye, kolon isimlerini yazıda sonradan Türkçe’ye dönüştürme gereği duydum. Düzeltirken 16. satır gözümden kaçmış, teşekkür ederim yorumunuz için.

  4. Javascript ile SQL bağlantı kodlarını yazdık ancak bu kodlar kullanıcı tarafından görülmeyecek mi, bu bir güvenlik açığı değil mi?

    • UI (kullanıcı arayüzü) tarafında yazılan kodlar sadece uygulamayı kullananlar tarafından görülür. Server tarafında yazılan JS kodları kullanıcı tarafında görünmez. Bu nedenle bir güvenlik açığı bulunmuyor. (SQL Injection ve CSRF açıklarını kapattığınızı varsayıyorum). Özetle, server tarafında JavaScript yazdığımız için kullanıcı yorumlanıp (interpret) oluşan sonucu görür, yazılan kodları değil (Php gibi).

  5. Örneğe felixge modülünü eklemeye çalışıyorum biraz uğraştırıyor. Modülün tırnakları nedeniyle ekranda gösterme ve veritabanına ekleme kısmında değişiklik yapmak gerekiyor.

  6. Merhaba öncelikle, bilgileirnizi paylaştığınız için çok teşekkür ederim, aklıma takılan birşeyi sormak istiyrum. Mysql e bu şekilde bağlandığımızda her işlemden sonra sorguyu kapatmamız gerekmezmi başka örneklerde öyle gördüm gibi, birde pool connection dedikleri bir bağlanma tipi var kapatmamak için bunu kullanıyor olabilirler. Ben tam anlayamadım bu konuyla ilgili bir fikriniz var mı ?

  7. Hocam merhaba bir sorum olacaktı, 8000 portunu kullanmak şart mı? Localde default port olan 80 portu üzerinden yapabilir miyiz? Birde eklenen veri, php tarafından eklensede otomatik olarak okunur ve gelir değil mi?

Yazı hakkında görüşlerinizi belirtmek istermisiniz?

Daha fazla Facebook, Html/Html5, JQuery, MySQL, Node.js
Kapat