7 Ağustos 2012 Salı

Socket.io Nedir?


Socket.io'nun amacı, gerçek zamanlı olarak hemen hemen her tarayıcı ile (mobil cihazlar dahil) farklı iletişim protokollerine rağmen iletişim kurabilmelerini sağlamak.

Sunucu ve client tarafında anlık iletişimi sağlamak ve bunun için hemen hemen her tarayıcı ile ve çok farklı protokollerle çalışmayı hedeflemiş olan bu yapıyı beraber inceleyelim.

WebMatrix kullanarak boş bir NodeJS şablonu açtıktan sonra, komut satırı ile ilgili klasöre gelelim.

npm install express socket.io

Gerekli olan kurulumlar tamamlandık böylece. Express ile ilgili ayarları, daha önceki konularda bahsettiğimiz için geçiyorum.

var socket = require('socket.io');
var io = socket.listen(8888);

io.sockets.on('connection', function(socket) {
    socket.emit('news', { hello: 'world' });
    socket.on('my other event', function(data) {
        console.log(data);
    });
});

Tanımlanan Socket.IO ile 8888 portu üstünden kurulum yapılıyor. Sunucu tarafında bu kodlar ile başlayalım. İncelemek gerekirse, 'connection' adında bir event bekleniyor. Bu event ile 'news' adında başka bir event ile 
{ hello: 'world' } JSON objesi gönderiliyor ve sonrasında 'my other event' adında başka bir event bekleniyor. Bu event ile gelen veriyi de ekranda gösterelim istedik.

Client tarafında Socket.IO kullanabilmek için, tabiki de sunucu ile aynı porttan iletişime geçmemiz gerekiyor. İnceleme için index.html dosyası içerisinde client kodlarımız bakalım.

HTML sayfamız içerisinde head tag'ı arasında

<script src="http://localhost:8888/socket.io/socket.io.js"></script>

kodunu eklememiz gerekiyor. Body bölümünde ise gereken diğer kodları ekleyip bunları açıklayalım.
<script>
    var socket = io.connect('http://localhost:8888');
    socket.on('news', function(data) {
        console.log(data);
        if(document.all){
            document.getElementById('income-data').innerText =JSON.stringify(data);
        } else{
            document.getElementById('income-data').textContent = JSON.stringify(data);
        }
        socket.emit('my other event', { my: 'data' });
    });
</script>

Önce hangi porttan bağlandığımızı belirtiyoruz. Her client 'connection' adındaki event'i ilk bağlantı kurulduğunda göndermektedir. Kalp atışına başladıktan sonra, 'news' adındaki event için bekliyor. Gelen veriyi, 'income-data' içerisine yazıp 'my other event' adındaki event'i gönderiyor.

Süreci özetleyip toparlamak gerekirse şöyledir. Sunucu tarafındaki kodlarımız, herhangi bir client isteği gelince ('connection') onlara { hello: 'world' } diyerek selam verecektir ve onların başka bir event ('my other event') göndermesini bekleyecektir.

Client tarafında ise, 'news' diyerek gelen veriyi alıp karşılık olarak ('my other event') gönderilecektir.



Komut satırı ile çalıştırdığımızdaki görüntüsü yukarıdaki gibidir. WebMatrix ile komut satırındaki gibi kayıtlara bakabiliyoruz.



Sunucu ve client için ayrı ayrı gelen giden tüm dataları detaylıca görebiliyoruz. Örnek kodun tamamını ve sürüm bilgilerini yazının sonunda bulabilirsiniz.

Kısa anlatımdan sonra Socket.IO hakkında biraz daha derin bilgilere geçebiliriz.
// io.listen(<port>) kodu otomatik olarak http server ayağa kaldırmaktadır.
var io = require('socket.io').listen(80);
// sunucumuzu 80 portu için ayarlıyoruz
io.sockets.on('connection', function(socket) {
    //'connection' bağlantının kurulmasını bekler.
    io.sockets.emit('this', { will: 'be received by everyone' });
    //gelen bağlantıya cevap olarak io.sockets.emit şeklinde cevap verirsek
    //io üzerindeki herkese cevap göndermiş oluruz.
    socket.on('message', function(from, msg) {
        //kaynağına göre özel mesaj gönderilmişse
        console.log('I received a private message by ', from, ' saying ', msg);
    });
 
    socket.on('disconnect', function() {
        //kullanıcı tarafında bağlantı koptuğu anda
        io.sockets.emit('user disconnected');
    });
});

Socket.IO üzerinde bazı ön tanımlı eventler vardır. Bunlar 'connection''private message', 'disconnect' şeklindedir.
Sırasıyla bağlantı kurulduğunda, mesaj gönderildiğinde ve bağlantı kesildiğinde gönderilmek üzere kurgulanmış eventlerdir.


// io.listen(<port>) kodu otomatik olarak http server ayağa kaldırmaktadır.
var io = require('socket.io').listen(80);
io.sockets.on('connection', function(socket) {
    socket.on('set nickname', function(name) {
        socket.set('nickname', name, function() {
            //set methodu ile session olarak kullanıcı ile server
            //arasında veri tutabiliriz.
            socket.emit('ready');
        });
    });
 
    socket.on('msg', function() {
        socket.get('nickname', function(err, name) {
            //bu veriyi get ile çekebiliriz.
            console.log('Chat message by ', name);
        });
    });
});

Peki bazı verileri kaydetmemiz gerekirse, çok önemli olmayan -database kaydı gerektirmeyen- verilerimizi oturum bazlı olarak kaydedebiliriz.

Bağlantı kesildiğinde bu veriler otomatik olarak silinmektedir.
var chat = io
  .of('/chat')
  .on('connection', function(socket) {
      //sadece '/chat' url'i altında çalışacaktır
      socket.emit('a message', {
          that: 'only'
      , '/chat': 'will get'
      });
      chat.emit('a message', {
          everyone: 'in'
      , '/chat': 'will get'
      });
  });
 
var news = io
  .of('/news')
  .on('connection', function(socket) {
      //sadece '/news' url'i altında çalışacaktır
      socket.emit('item', { news: 'item' });
  });

Url bazlı filtrelemeler yapabilmek için bu şekilde tanımlamalar yapabiliyoruz.
//SERVER
io.sockets.on('connection', function(socket) {
    //bağlantı kurulduğunda
    socket.on('ferret', function(name, fn) {
        //ferret event'ini dinleyecek
        //gelen parametreyi alıp fn fonksiyonu ile donecektir.
        fn('woot');
        // data olarak 'woot' gönderilecektir
    });
});
//SERVER

<!-- CLIENT -->
<script>
        var socket = io.connect(); 
    // ilgili bağlantıları otomatik bulmak için parametre girmeyin
        socket.on('connect', function () { 
    // 'connect' için doğru bir kullanım değildir. örnek içindir.
          socket.emit('ferret', 'tobi', function (data) {
            console.log(data); // woot datası gelecektir.
          });
        });
</script>
<!-- CLIENT -->

Bazı durumlarda client tarafında veriyi gönderdikten sonra dönen sonuca da ihtiyacımız vardır. Bunun en kolay yolu, .send ya da .emit methodlarına fazladan bir parametre ile bir fonksiyon göndermektir.

GitHub
NodeJS 0.8.4
express@3.0.0rc2 node_modules\express
├── methods@0.0.1
├── range-parser@0.0.4
├── fresh@0.1.0
├── cookie@0.0.4
├── commander@0.6.1
├── debug@0.7.0
├── mkdirp@0.3.3
├── crc@0.2.0
├── send@0.0.3 (mime@1.2.6)
└── connect@2.4.2 (pause@0.0.1, bytes@0.1.0, formidable@1.0.11, qs@0.4.2)
socket.io@0.9.9 node_modules\socket.io
├── policyfile@0.0.4
├── redis@0.7.2
└── socket.io-client@0.9.9 (xmlhttprequest@1.4.2, uglify-js@1.2.5, active-x-obfuscator@0.0.1, ws@0.4.21)

7 yorum:

  1. socket.io ile ufak bir uygulamam var, browser açık iken node'u kapatıp açtığımda browser'a her seferinde artacak şekilde resultset dönüyor?bunun sebebi sizce ne olabilir?

    YanıtlaSil
  2. Selamlar Oğuzhan, sorununu tam olarak anlayamadım. Daha detaylı açıklayabilirsen yardımcı olmaya çalışalım...

    YanıtlaSil
  3. Merhaba hocam, Node.js ile yazdığım sohbet (mini) ie9 da çalışıyor , chrome da düzgün çalışmıyor neden acaba hocam .. Yardımcı olursanız sevinirim. Kod linktedir..

    https://github.com/veyselkoparal/Sohbet

    YanıtlaSil
  4. Merhaba Veysel, kodu indirip çalıştırdım. index.html sayfanda jquery scriptini

    src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"

    şu adresten almaya çalışıyorsun başında http olması gerekiyor. bu şekilde düzelterek chrome ve ie9 da kodunu çalıştırdım.
    olması gereken src adresi:
    "http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"

    YanıtlaSil
  5. Merhaba Ertuğrul,

    Kaynağı değiştirdim, güncel jquery yi ekledim veya senin verdiğin linki sorun çıkartıyor hala.

    YanıtlaSil
  6. İstersen şu uygulamayı hem chrome hemde ie9 yada firefox ta dene.. 2 sinde farklı sonuçlar veriyor.. yanlış bir şey de yok ?

    https://github.com/veyselkoparal/nodechat2

    YanıtlaSil
  7. Merhabalar, Bir şey buldum onu bahsedeyim.

    Dedim ya, chrome da sistem çalışmıyor örnek https://github.com/veyselkoparal/nodechat2

    server.js yi çalıştırıyorum.. chrome ile bağlanıyorum (tabi çalışmıyor) daha sonra server.js yi kapatıyorum chrome açık kalıyor.. chrome u kapatmadan tekrar server.js yi çalıştırdığımda , server.js chrome da çalışıyor. anlam veremedim.

    YanıtlaSil