О WebSocket-ах на примере реализации чата мгновенных сообщений с помощью node.JS

2011-07-02

Цель этой статьи — на простом примере ознакомится с новым, еще непривычным, подходом в организации взаимодействия веб-приложений с сервером. В качестве «Hello World»-приложения для этой технологии нам отлично послужит чат. В статье будет продемонстрирована реализация серверной и клиентской частей приложения, чтобы лучше понимать как они взаимодействуют.

В протоколе HTTP версии 1.1 была реализована возможность удерживать соединения. Осуществлена она с помощью заголовка Keep-Alive. Веб-приложение соединяется с серверной стороной с помощью WebSocket-тов, и удерживает соединение. Этим временем, браузер с сервером могут обмениваться информацией, что происходит практически мгновенно. Важная особенность этого взаимодействия состоит в том, что сервер способен сам отправлять сообщения клиенту, когда это нужно, тем самым — инициировать некие действия на этом клиенте.

Ну что же, приступим к созданию нашего чата. И первое, что нам предстоит реализовать — это сервер. Сервер мы напишем на node.JS.

Идея такова:
Мы создадим WebSocket-сервер, который будет прослушивать порт 8888, и ожидать подключений клиентов. Все клиенты будут сохранятся в массиве. При получении сообщения от любого из них, это сообщение будет разослано всему списку пользователей, с которыми установлены соединения. При отключении клиента и закрытии соединения, соответствующий пользователь будет удален из массива.

Мы воспользуемся библиотекой для реализации web-socket-ов в Node.JS, которую создал Jacek Becela. Её можно скачать по ссылке http://github.com/ncr/node.ws.js. После это её нужно положить в тот же каталог, в котором будет лежать серверная часть нашего чата. Нас интересует именно файл с названием ws.js.

Создадим файл с названием server.js и поместим в него такой код:

var sys = require("sys");
// подключаем библиотеку для создания web-socket-сервера
var ws = require("./ws.js");
// объявляем массив, в котором будем хранить весь список подключённых пользователей
var clientsArr = [];
// создаем веб-сокет-сервер
var wsServer = ws.createServer(function(websocket){
// добавляем обработчик события,
// которое сработает при подключении нового пользователя
websocket.addListener("connect", function() {
// добавляем это соединения в массив пользователей
clientsArr.push(websocket);
sys.debug("Connection. Clients amount: "+clientsArr.length);
});
// добавляем обработчик события,
// которое сработает при получении новых данных от пользователя,
// а точнее, когда пользователь отправит сообщение
websocket.addListener("data", function(data) {
// выведем сообщение в терминал на сервере
sys.debug(data);
// Рассылаем это сообщение всему списку подключенных пользователей
for(var i=0, l=clientsArr.length; i<l; i++) {
clientsArr[i].write(data);
}
});
// добавляем обработчик события,
// которое сработает при закрытии соединения с пользователем
websocket.addListener("close", function() {
// найдём, какое именно соединение было закрыто
// и удалим его из списка пользователей
for(var i=0, l=clientsArr.length; i<l; i++) {
if(websocket == clientsArr[i]) {
clientsArr.splice(i,1);
sys.debug("Disconnection. Clients amount: "+clientsArr.length);
break;
}
}
});
});
// поставим наш сервер на прослушивание 8888-го порта
// на наличие подключений и новых сообщений
wsServer.listen(8888);
// Выведем отладочную информацию в терминале на сервере с адресом этого сервера,
// по которому нужно подключатся клиентам
sys.debug("Server running at ws://192.168.0.1:8888");

Сервер на node.JS готов. Запустим его, выполнив команду в консоле:

node server.js

Осталось написать клиентскую часть для нашего чата, приступим.

Стандарт HTML5 включает в себя WebSocket-и и, тем самым, добавляет браузеру возможность соединятся с сервером и общаться с ним. Этим и воспользуемся при создании нашего чата.

Примечание:
На данный момент веб-сокеты реализованы только в браузерах на основе WebKit, то-есть в Chrome и Safari. Но, можно заставить и другие браузеры работать через веб-сокеты с помощью дополнительных javascript-библиотек, использующих возможности flash-а.
В данной статье это не будет рассматриваться.

Сначала реализуем html-структуру.
Собственно, нам нужно:
— поле для ввода сообщений;
— кнопка, по нажатию которой, сообщение будет отправляться серверу;
— область, в которой будут отображаться все сообщения.

Создадим файл с именем index.html и добавим в него, примерно такой, код:

<!DOCTYPE HTML>
<html>
<head>
<title>Chat on WebSockets made on node.JS</title>
</head>
<body>
<!-- Поле для ввода сообщений -->
<input type="text" id="message" />
<!-- Кнопка для отправки сообщений -->
<input type="button" id="sendButton" value="send" />
<hr />
<!-- Область для вывода всех сообщений -->
<div id="messageList"></div>
<!-- Подключаем скрипт, реализующий клиентскую часть функционала -->
<script src="client.js"></script>
</body>
</html>

Как Вы, наверное, догадались — нам еще осталось создать файл client.js и реализовать в нём «возможность общения» с сервером. Нормальный диалог предусматривает возможность отправки и приема сообщений. То-есть в первую очередь мы реализуем обработчик нажатия кнопки отправки, а во вторых — будем слушать сервер, который будет присылать нам сообщения наших собеседников.

Код:

// спрашиваем пользователя его имя
var userName = prompt("Enter your name:");
// получаем ссылки на необходимые нам DOM-элементы:
// поле ввода, кнопки, список сообщений
var msg = document.getElementById("message");
var sendBtn = document.getElementById("sendButton");
var msgList = document.getElementById("messageList");
// Проверяем, поддерживает ли браузер веб-сокеты
if(typeof(WebSocket)=="undefined") {
// если не поддерживает - сообщаем об этом пользователю
alert("Your browser does not support WebSockets. Try to use Chrome or Safari.");
} else {
// иначе - создаем соединение с сервером,
// указывая в качестве параметра его адрес и порт.
// Обратите внимание на то, что используется протокол "ws" (сокращенно от WebSocket).
var ws = new WebSocket("ws://192.168.0.1:8888");
// создаем обработчик нажатия кнопки, по нажатию на которую,
// мы отправим сообщение на сервер и очистим поле для ввода сообщений
sendBtn.onclick = function() {
ws.send(userName+": "+msg.value);
msg.value = "";
}
// создаем обработчик события "onmessage",
// которое сработает, когда сервер пришлёт нам сообщение
ws.onmessage = function(event) {
// добавляем пришедшее сообщение в список
msgList.innerHTML = event.data+"<hr />" + msgList.innerHTML;
}
}

Вот и всё, наш чат мгновенных сообщений готов.

Очевидно, что данный механизм клиент-серверного взаимодействия добавляет веб-разработчикам новые грандиозные возможности и огромное пространство для фантазий. С помощью данной технологии можно делать мультипользовательские онлайн-игры реального времени, различные системы мониторинга, аналоги сетевым десктопным-программам, таким как ICQ, Skype, запускать обновления чего либо по инициативе сервера и много чего другого.



12 комментариев на «О WebSocket-ах на примере реализации чата мгновенных сообщений с помощью node.JS»

  1. RedSpirit:

    Отличный, простой и понятный туториал по ВебСокетам, как раз то, что искал. Спасибо! )

  2. Destr:

    Выглядит очень хорошо, но у меня возникла проблема.
    Нет ошибок ни на серверной, ни на клиентской части, но между тем сервер никак не реагирует на попытки подключится.

    Ubuntu 10.04 LTS
    node v0.2.6, v0.4.12
    google chrome 14.0.835.186

  3. Юрий:

    тоже не реагирует на попытки соединения. я вот не могу понять — на каком адресе поднимается сервер? где это настраивается? просьба отмветить на мой емэил jericoСАБАКАinbox.ru

  4. kotakota:

    красава, спасибо за туториал ;) помог

  5. DenG:

    Не тупите люди. Просто поменяйте адрес сервера в client.js

  6. Музыкант:

    Статья вроде понятная и хорошая, но есть вопросы.
    1. под windows работать может локально (для теста)? — у меня не получилось
    2. на хостинге если запустить хостер не выругается?
    3. вместо ip алиас можно прописывать?

  7. Денис:

    нихуя эта ебата не работает !! !

  8. Илья:

    Тоже ничего не работает. Сервер вот запускается, но при отправке сообщений в чате ноль реакции

  9. Дмитрий:

    Непонятно, как обращаться с node.js, что это вообще за штука??? через какую консоль нужно запускать server.js? Статья вроде грамотная, но написана явно для просветленных, а как же быть тем, кто первый раз слышит о node.js

  10. Александр:

    Вопрос а как отправить определенному пользователю а не всем?

  11. Паша:

    Не работает. Сервер вылетает с ошибками.

Добавить комментарий