Standardowy czat: użytkownik wysyła komunikat, który serwer rozsyła do wszystkich połączonych użytkowników.
Aplikacja została zaimplementowana w oparciu o protokół Websocket z wykorzystaniem modułu Socket.IO
Struktura plików aplikacji podana jest na poniższym obrazku.
. ├── Gruntfile.js ├── package.json ├── public │ ├── css │ │ └── styl.css │ ├── img │ │ ├── bullet_green.png │ │ └── bullet_red.png │ ├── index.html │ └── js │ └── skrypt.js └── serwer.js
Główne pliki w tej implementacji — to: index.html,script.js, serwer.js.
index.htmlTen plik jest wysyłany do klienta bez zmian. Zawiera on podstawowe drzewo DOM strony. Drzewo to będzie uzupełniane i modyfikowane dynamiczne po stronie klienta.
script.jsTen plik zawiera aplikację kliencką.
serwer.jsW tym pliku jest aplikacja serwerowa.
W aplikacji utworzono dwa serwery: standardowy HTTP oraz serwer Websocket[1]
var express = require('express');
var app = express();
var httpServer = require("http").Server(app);
var io = require("socket.io")(httpServer);
Przy połączeniu (zdarzenie connection) na obiekcie socket, który odpowiada klientowi, rejestruje się dwa callbacki: na zdarzenie message (komunikat od klienta) oraz zdarzenie error.
io.sockets.on("connection", function (socket) {
socket.on("message", function (data) {
io.sockets.emit("echo", "No tak, tak – dostałem: " + data);
});
socket.on("error", function (err) {
console.dir(err);
});
});
W momencie, kiedy drzewo DOM już jest zbudowano, wywołana jest funkcja, wykonująca następujące czynności:
Otrzymuje dostęp do elementów DOM poprzez odpowiednie zmienne:
var status = document.getElementById("status");
var open = document.getElementById("open");
var close = document.getElementById("close");
var send = document.getElementById("send");
var text = document.getElementById("text");
var message = document.getElementById("message");
Określa obiekt socket, który będzie odpowiadał za połączenie z serwerem:
var socket;
Ustawia początkowe właściwości elementów DOM:
status.textContent = "Brak połącznia"; close.disabled = true; send.disabled = true;
Po kliknięciu na przycisk „Połącz” (element open) nawiązuje się nowe połączenie Websocket:
open.addEventListener("click", function (event) {
open.disabled = true;
if (!socket || !socket.connected) {
socket = io({forceNew: true});
}
Oraz ustawia się callbacki na zdarzenia:
connect — zmiana ustawień elementów:
socket.on('connect', function () {
close.disabled = false;
send.disabled = false;
status.src = "img/bullet_green.png";
console.log('Nawiązano połączenie przez Socket.io');
});
disconnect — przywrócenie ustawień elementów:
socket.on('disconnect', function () {
open.disabled = false;
status.src = "img/bullet_red.png";
console.log('Połączenie przez Socket.io zostało zakończone');
});
error — wyświetlenie komunikatu o błędzie:
socket.on("error", function (err) {
message.textContent = "Błąd połączenia z serwerem: '"
+ JSON.stringify(err) + "'";
});
echo — wyświetlenie komunikatu, otrzymanego z serwera:
socket.on("echo", function (data) {
message.textContent = "Serwer twierdzi, że otrzymał od Ciebie: '"
+ data + "'";
});
Po kliknięciu na przycisk „Rozłącz” (element close) połączenia się rozłącza i stosownie zmienia się ustawienia:
close.addEventListener("click", function (event) {
close.disabled = true;
send.disabled = true;
open.disabled = false;
message.textContent = "";
socket.io.disconnect();
console.dir(socket);
});
Po kliknięciu na przycisk „Wyślij” (element send) wysyła się tekst komunikatu na serwer.
send.addEventListener("click", function (event) {
socket.emit('message', text.value);
console.log('Wysłałem wiadomość: ' + text.value);
text.value = "";
});
Na serwerze dla tego klienta odpala się zdarzenie message — wynika to z powyższego kodu.
Nawias zamykający funkcji:
});
[1] Moduł Socket.IO emuluje protokół Websocket dla przeglądarek, które nie obsługują tego protokołu. Jednak takie przeglądarki są bardzo rzadkie.