Websoket teknolojisi ile TCP bağlantısı üzerinden çift yönlü mesaj gönderebilme özelliği sayesinde, backende...
- Gençay Yıldız
- 07 Mayıs 2019
- 2629 kez görüntülendi.
Bundan yıllar yıllar öncesine kadar(yani geçen yıla kadar) web yapılanmalarında gerçek zamanlı işler yapılacağı zaman Ajax teknolojisi kullanılarak, belli aralıklarla 1 saniye – milisaniye yapılan sorgular neticesinde sanki gerçek zamanlı bir sistem izlenimi veren yapılar üzerinde çalışıyorduk. Dolayısıyla sistemin canlılık durumunu kusursuz sağlayabilmek için Backend’e yapılacak sorgu aralığını mümkün mertebe azaltarak, sistemin kullanıcıya dönük işleyişinde gerçek zamanlılık özelliğini arttırmayı tercih ederdik. Hal böyleyken, mikro aralıklarla yapılan her bir talep neticesinde bilanço bizlere yüksek maliyet ve performans kaybı olarak yansımaktaydı. Vee tabi tüm bu süreç Http protokolü üzerinden gerçekleşmekte ve yapılan her bir talebe karşılık ihtiyaç olmaksızın bir cevap alınmaktaydı.
Websoket teknolojisi ile TCP bağlantısı üzerinden çift yönlü mesaj gönderebilme özelliği sayesinde, backende micro aralıklarla yapılan talep yoğunluğu neticesinde ödenen yüksek maliyetten kurtulunmakta ve gerçek zamanlı uygulamaları dört dörtlük bir şekilde uygulayabilme şansı elde etmekteyiz.
Evet… Websoket teknolojisi; sürekli açık olan bir TCP bağlantısı üzerinden çift yönlü mesaj gönderebilme işlemini yapabilen bir protokoldür. Bu açık TCP protokolü üzerinden taraflardan isteyen istediğine mesaj gönderebilmektedir ve HTTP protokolünde olduğu gibi gönderilen mesajlara cevap verme zorunluluğu bulunmamaktadır. O yüzden burada “talep(request)” / “cevap(response)” terminolojisinden ziyade sadece “mesaj/message/data” terminolojisi tercih edilmektedir.
Yukarıdaki şemadan HTTP/REST Request işlevselliğini incelerseniz eğer her bir requeste karşılık bir response olduğunu göreceksiniz. HTTP protokolünde requeste karşılık dönülecek bir data olsun olmasın bir response dönülmesi mecburidir.
Websocket şemasını incelerseniz eğer açık bir TCP bağlantısı üzerinden tüm süreç işlemektedir. Handshake(el sıkışma/tokalaşma) işleminin ardından Acknowledgement(onay/tasdik) yapıldıktan sonra Bi-directional message(çift yönlü mesajlaşma) süreci başlamaktadır. Taa ki connection end olana kadar.
Kısaca Websocket teknolojisinde;
- Bir istekte bulunulduğu zaman cevap beklenilmemektedir. Tabi isteğe ya da ihtiyaca göre cevapta dönülebilir.
- Client server’a, server client’a veri gönderebilir. Çift yönlü mesajlaşma.
- Server, gelen verileri abonelere iletir.
- İki taraf gönderdiği mesajlara cevap beklememektedir.
Socket.IO Modülü
Node.js’de websocket işlemleri için kullanacağımız modül socket.io modülüdür. Socket.IO; websocket ile ilgili protokollerin tamamını (XHR, Long Polling, Websocket) standartlaştıran ve sabit bir kullanım sunan websocket emülatörüdür.
Hoca emülatör ne la? diye soranlarınıza genel kültür mahiyetinde aşağıdaki açıklamayı sunalım.
Bir sistemin başka bir sistem üzerinde çalıştırılmasına emülasyon, bu işlevi yapan yazılımlara emülatör denir.
Socket.IO modülünün Node.js ile kusursuz bir kullanımı vardır.
İlgili modülü projenize entegre edebilmek için aşağıdaki kodu çalıştırmanız yeterlidir.
npm i socket.io --save
Server ile Client Arasında TCP Bağlantısı Oluşturmak
const http = require("http"); const socket = require("socket.io"); const server = http.createServer((request, response) => { response.end("..."); }); server.listen(1234); //1234 portuna gelecek olan tüm istekleri socket tarafından dinlememiz gerekmektedir. const io = socket.listen(server); //socket tarafından ilgili server dinlenmeye alınmıştır. Dolayısıyla gelecek olan tüm talepler socket tarafından yakalanacaktır. //Bu şekilde her talep neticesinde server ile client arasında aktif bir TCP bağlantısı oluşturulacaktır.
Önceki yazılarımızda kaleme aldığımız Node.js’de Http Sunucusu Oluşturalım başlıklı makalemizde belirttiğimiz üzere bir server oluşturmaktayız. Oluşturulan bu server’a karşı olan tüm talepleri, bağlantıları vs. dinleyebilmek için “socket.io” modülü tarafından ilgili server dinlenmeye alınmaktadır. Bu dinleme neticesinde ilgili server ile client arasında aktif bir TCP bağlantısı oluşturulmaktadır.
Server’a bir client tarafından bağlantı sağlandığı zaman “connection” isimli bir event tetiklenecektir. Dolayısıyla bu event client’ın tüm bilgilerini beraberinde getirecektir.
io.sockets.on("connection", socket => { //Server'a bir client bağlandığı zaman "connection" isimli olay tetiklenecektir. socket parametresi ise bağlantı yapan client'ın bilgisini içermektedir. console.log("User connection", socket.client.id); });
Bu noktadan itibaren server kısmının inşası tamamdır. Şimdi bir client tasarlayalım ve açmış olduğumuz bu TCP bağlantısına connect edelim. Bizler bu içeriğimizde client’ı lalettayin bir html sayfası olarak tasarlayacağız.
<!DOCTYPE html> <html> <head> <script src="http://localhost:1234/socket.io/socket.io.js"></script> <script> const socket = io.connect("http://localhost:1234"); </script> </head> <body> <p> Merhaba, WebSocket </p> </body> </html>
Client tarafında dikkat edilmesi gereken husus “socket.io.js” isimli JavaScript kütüphanesinin kaynak olarak eklenmesidir. İlgili dosyaya, çalışma yaptığınız domain uzantısı üzerinden “http://***/socket.io/socket.io.js” kombinasyonu aracılığıyla erişebilirsiniz.
Yukarıdaki kod bloğuna dikkat ederseniz eğer server’da belirttiğimiz “1234” portuna yani “http://localhost:1234” adresine bir connect gerçekleştirilmektedir. Burada “io.connect()” fonksiyonuna “socket.io.js” kütüphanesi üzerinden erişilmektedir.
Şimdi bu html sayfasını açtığımız zaman, server’ı takip eden socket devreye girecek ve açık olan TCP bağlantısı üzerinden server’a mesaj gönderecektir.
Görüldüğü üzere…
Eğer ki client bağlantıyı kestiyse yani sayfayı kapattıysa “disconnect” olayı tetiklenecektir. Bu şekilde server tarafından ilgili client’a ait bağlantının son bulduğuna dair bilgi edinilecektir.
io.sockets.on("connection", socket => { console.log("User connection", socket.client.id); socket.on("disconnect", () => { console.log("User disconnect"); }); });
Yukarıdaki ekran görüntüsüne dikkat ederseniz sayfayı yeniden yüklediğimizde dahi önce bağlantıyı kesecek ardından yeniden bağlanacaktır. Bu detayıda gözden kaçırmamanızı öneririm…
Client ile Server’ın Haberleşmesi
Client ile server haberleşmesinde temel esas, iki taraftan birinin “emit” fonksiyonu ile olay yaratması ve diğerinin “on” fonksiyonu ile yaratılan olayı karşılaması üzerine kuruludur.
Örneğin;
Client’tan server’a haber gönderilecekse;
<!DOCTYPE html> <html> <head> <script src="http://localhost:1234/socket.io/socket.io.js"></script> <script> const socket = io.connect("http://localhost:1234"); socket.emit("sendMessageToServer"); //Client'tan server'a mesaj gönderirken burada "sendMessageToServer" adında bir olay yaratılmaktadır. Server'da bu olayı karşılayacaktır. </script> </head> <body> <p> Merhaba, WebSocket </p> </body> </html>
Görüldüğü gibi client’ta “emit” fonksiyonu ile “sendMessageToServer” adında bir olay yaratılmaktadır. Şimdi server’da bu olayı karşılayalım.
io.sockets.on("connection", socket => { console.log("User connection", socket.client.id); socket.on("disconnect", () => { console.log("User disconnect"); }); socket.on("sendMessageToServer", () => { console.log("sendMessageToServer tetiklendi."); }); });
Gördüğünüz üzere server’da ise “on” fonksiyonu ile “sendMessageToServer” olayı karşılanmıştır.
Server’dan client’a haber gönderilecekse;
io.sockets.on("connection", socket => { console.log("User connection", socket.client.id); socket.on("disconnect", () => { console.log("User disconnect"); }); socket.emit("sendMessageToClient"); });
“sendMessageToClient” isimli bir olay oluşturulmuştur. Şimdi client bu olaya “on” fonksiyonu ile bağlanacaktır.
<!DOCTYPE html> <html> <head> <script src="http://localhost:1234/socket.io/socket.io.js"></script> <script> const socket = io.connect("http://localhost:1234"); socket.on("sendMessageToClient", () => { //Server'da oluşturulan olay clientda on fonksiyonuyla karşılanmıştır. alert("sendMessageToClient tetiklendi."); }); </script> </head> <body> <p> Merhaba, WebSocket </p> </body> </html>
Burada son kez hatırlatma mahiyetinde HTTP protokolü değil websocket kullandığımızdan dolayı istek değil mesaj göndermekteyiz ve her gönderilen mesaj neticesinde cevap almak zorunda değiliz.
Haberleşme Esnasında Parametre Gönderme
Haberleşme sürecinde iki tarafta birbirlerine parametre gönderebilirler. Tabi bunun için olay yaratan tarafın yani “emit” fonksiyonunu kullanan tarafın ilgili fonksiyona ikinci parametreyi vermesi yeterlidir.
Şöyle ki;
Client’tan, server’a parametre gönderilecekse eğer;
<!DOCTYPE html> <html> <head> <script src="http://localhost:1234/socket.io/socket.io.js"></script> <script> const socket = io.connect("http://localhost:1234"); socket.emit("sendMessageToServer", 5); </script> </head> <body> <p> Merhaba, WebSocket </p> </body> </html>
Görüldüğü üzere “emit” fonksiyonunun ikinci parametresine server’a gönderilecek parametrenin değeri verilmektedir. Server’ın bu parametre değerini yakalayabilmesi için “on” fonksiyonunun callback fonksiyonuna belirteceği parametre iş görecektir.
io.sockets.on("connection", socket => { console.log("User connection", socket.client.id); socket.on("disconnect", () => { console.log("User disconnect"); }); socket.on("sendMessageToServer", data => console.log("Gönderilen parametre : " + data)); });
Benzer mantıkla;
Server’dan, client’a parametre gönderilecekse eğer;
io.sockets.on("connection", socket => { console.log("User connection", socket.client.id); socket.on("disconnect", () => { console.log("User disconnect"); }); socket.emit("sendMessageToClient", 5); });
<!DOCTYPE html> <html> <head> <script src="http://localhost:1234/socket.io/socket.io.js"></script> <script> const socket = io.connect("http://localhost:1234"); socket.emit("sendMessageToServer", 5); socket.on("sendMessageToClient", data => alert("Gönderilen parametre : " + data)); </script> </head> <body> <p> Merhaba, WebSocket </p> </body> </html>
Bu satırdan itibaren, Node.js’de gerçek zamanlı uygulamaların websocket ile nasıl temellendirildiğine ve client ile server arasındaki haberleşmenin nasıl yapıldığına dair teferruatlı değinmiş bulunmaktayız. Sonraki yazılarımızda Websocket kullanımına dair daha detaylı içerikler ile karşınızda olacağım.
Gençay Yıldız ın tüm makalelerine bu linkten ulaşabilirsiniz.
Bu yazıya 0 yorum yapılmış.