Socket.IO — Обзор
Socket.IO — это библиотека JavaScript для веб-приложений реального времени . Он обеспечивает двустороннюю связь в реальном времени между веб-клиентами и серверами. Он состоит из двух частей: клиентской библиотеки, которая запускается в браузере, и серверной библиотеки для node.js. Оба компонента имеют идентичный API.
Приложения в реальном времени
Приложение реального времени (RTA) — это приложение, которое функционирует в течение периода, который пользователь воспринимает как немедленный или текущий.
Некоторые примеры приложений в реальном времени —
-
Мессенджеры — приложения для чата, такие как Whatsapp, Facebook Messenger и т. Д. Вам не нужно обновлять свое приложение / веб-сайт для получения новых сообщений.
-
Push-уведомления — когда кто-то помечает вас на фотографии в Facebook, вы сразу получаете уведомление.
-
Приложения для совместной работы — приложения, такие как Google Docs, которые позволяют нескольким людям одновременно обновлять одни и те же документы и вносить изменения во все экземпляры людей.
-
Онлайн-игры — такие игры, как Counter Strike, Call of Duty и т. Д., Также являются примерами приложений в реальном времени.
Мессенджеры — приложения для чата, такие как Whatsapp, Facebook Messenger и т. Д. Вам не нужно обновлять свое приложение / веб-сайт для получения новых сообщений.
Push-уведомления — когда кто-то помечает вас на фотографии в Facebook, вы сразу получаете уведомление.
Приложения для совместной работы — приложения, такие как Google Docs, которые позволяют нескольким людям одновременно обновлять одни и те же документы и вносить изменения во все экземпляры людей.
Онлайн-игры — такие игры, как Counter Strike, Call of Duty и т. Д., Также являются примерами приложений в реальном времени.
Почему Socket.IO?
Написание приложения для реального времени с использованием популярных стеков веб-приложений, таких как LAMP (PHP), традиционно было очень трудным. Он включает в себя опрос сервера на наличие изменений, отслеживание временных меток, и это намного медленнее, чем должно быть.
Сокеты традиционно были решением, вокруг которого строится большинство систем реального времени, обеспечивая двунаправленный канал связи между клиентом и сервером. Это означает, что сервер может отправлять сообщения клиентам. Всякий раз, когда происходит событие, идея заключается в том, что сервер получит его и отправит заинтересованным подключенным клиентам.
Socket.IO довольно популярен, его используют Microsoft Office, Yammer, Zendesk, Trello и многие другие организации для создания надежных систем реального времени. Это одна из самых мощных JavaScript-фреймворков на GitHub и наиболее зависимая от модуля NPM (Node Package Manager). Socket.IO также имеет огромное сообщество, что означает, что найти помощь довольно легко.
ExpressJS
Мы будем использовать Express для создания веб-сервера, с которым будет работать Socket.IO. Можно использовать любую другую инфраструктуру на стороне узла или даже HTTP-сервер узла. Тем не менее, ExpressJS позволяет легко определять маршруты и другие вещи. Чтобы узнать больше о Express и получить общее представление о нем, перейдите к учебнику по ExpressJS .
Socket.IO — Окружающая среда
Чтобы начать разработку с использованием Socket.IO , вам нужно установить Node и npm (менеджер пакетов узлов) . Если у вас их нет, перейдите к настройке узла для установки узла в вашей локальной системе. Убедитесь, что узел и npm установлены, выполнив следующие команды в вашем терминале.
node --version npm --version
Вы должны получить вывод, похожий на —
v5.0.0 3.5.2
Откройте свой терминал и введите следующее в своем терминале, чтобы создать новую папку, и введите следующие команды:
$ mkdir test-project $ cd test-proect $ npm init
Он задаст вам несколько вопросов; ответьте на них следующим образом —
Это создаст файл конфигурации «package.json node.js» . Теперь нам нужно установить Express и Socket.IO . Чтобы установить их и сохранить в файле package.json , введите следующую команду на своем терминале в каталог проекта.
npm install --save express socket.io
И последнее, что мы должны продолжать перезагружать сервер. Когда мы вносим изменения, нам понадобится инструмент под названием nodemon. Чтобы установить nodemon , откройте свой терминал и введите следующую команду —
npm install -g nodemon
Всякий раз, когда вам нужно запустить сервер, вместо использования узла app.js используйте nodemon app.js. Это гарантирует, что вам не нужно перезагружать сервер при каждом изменении файла. Это ускоряет процесс разработки.
Теперь у нас настроена среда разработки. Давайте теперь приступим к разработке приложений для реального времени с Socket.IO.
Socket.IO — Hello World
Создайте файл с именем app.js и введите следующий код для настройки экспресс-приложения:
var app = require('express')(); var http = require('http').Server(app); app.get('/', function(req, res) { res.sendfile('index.html'); }); http.listen(3000, function() { console.log('listening on *:3000'); });
Нам понадобится файл index.html для обслуживания, создайте новый файл с именем index.html и введите в него следующий код:
<!DOCTYPE html> <html> <head> <title>Hello world</title> </head> <body>Hello world</body> </html>
Чтобы проверить, работает ли это, перейдите в терминал и запустите это приложение, используя следующую команду —
nodemon app.js
Это запустит сервер на локальном хосте: 3000. Зайдите в браузер и введите localhost: 3000, чтобы проверить это.
Это настраивает наше экспресс-приложение и теперь подает файл HTML по корневому маршруту. Теперь нам потребуется Socket.IO и будет регистрироваться «Пользователь подключен», каждый раз, когда пользователь заходит на эту страницу, и «Пользователь отключен», каждый раз, когда кто-то покидает / закрывает эту страницу.
var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); app.get('/', function(req, res) { res.sendfile('index.html'); }); //Whenever someone connects this gets executed io.on('connection', function(socket) { console.log('A user connected'); //Whenever someone disconnects this piece of code executed socket.on('disconnect', function () { console.log('A user disconnected'); }); }); http.listen(3000, function() { console.log('listening on *:3000'); });
Require (‘socket.io’) (http) создает новый экземпляр socket.io, подключенный к http-серверу. Обработчик событий io.on обрабатывает события подключения, отключения и т. Д. В нем, используя объект сокета.
Мы настроили наш сервер для регистрации сообщений о подключениях и отключениях. Теперь мы должны включить клиентский скрипт и инициализировать объект сокета, чтобы клиенты могли устанавливать соединения при необходимости. Сценарий обслуживается нашим сервером io по адресу /socket.io/socket.io.js .
После выполнения описанной выше процедуры файл index.html будет выглядеть следующим образом:
<!DOCTYPE html> <html> <head> <title>Hello world</title> </head> <script src = "/socket.io/socket.io.js"></script> <script> var socket = io(); </script> <body>Hello world</body> </html>
Если вы перейдете на localhost: 3000 сейчас (убедитесь, что ваш сервер работает), вы получите распечатку Hello World в вашем браузере. Теперь проверьте журналы консоли вашего сервера, она покажет следующее сообщение —
A user connected
Если вы обновите свой браузер, он отключит сокет и восстановит соединение. В журналах консоли вы можете увидеть следующее:
A user connected A user disconnected A user connected
Теперь у нас работают сокетные соединения. Вот как легко настроить соединения в Socket.IO.
Socket.IO — обработка событий
Сокеты работают на основе событий. Существуют некоторые зарезервированные события, доступ к которым можно получить с помощью объекта сокета на стороне сервера.
Это —
- соединять
- Сообщение
- Отключить
- Заново
- пинг
- Присоединяйтесь и
- Покидать
Объект сокета на стороне клиента также предоставляет нам некоторые зарезервированные события, которые:
- соединять
- Connect_error
- connect_timeout
- Переподключение и т. Д.
В примере Hello World мы использовали события подключения и отключения для регистрации, когда пользователь подключился и ушел. Теперь мы будем использовать событие message для передачи сообщения с сервера клиенту. Для этого измените вызов io.on («соединение», функция (сокет)), включив в него следующее:
var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); app.get('/', function(req, res) { res.sendfile('index.html'); }); io.on('connection', function(socket) { console.log('A user connected'); //Send a message after a timeout of 4seconds setTimeout(function() { socket.send('Sent a message 4seconds after connection!'); }, 4000); socket.on('disconnect', function () { console.log('A user disconnected'); }); }); http.listen(3000, function() { console.log('listening on *:3000'); });
Это отправит событие под названием сообщение (встроенное) нашему клиенту через четыре секунды после подключения клиента. Функция send объекта сокета связывает событие message.
Теперь нам нужно обработать это событие на нашей стороне клиента. Таким образом, отредактируйте тег сценария index.html, включив в него следующий код:
<script> var socket = io(); socket.on('message', function(data){document.write(data)}); </script>
Сейчас мы обрабатываем событие «message» на клиенте. Когда вы перейдете на страницу в вашем браузере сейчас, вам будет представлен следующий скриншот.
Через 4 секунды сервер отправляет событие сообщения, наш клиент обработает его и выдаст следующий вывод:
Примечание. Мы отправили здесь текстовую строку; мы также можем отправить объект в любом случае.
Сообщение было встроенным событием, предоставляемым API, но оно мало используется в реальном приложении, так как мы должны иметь возможность различать события.
Для этого Socket.IO предоставляет нам возможность создавать собственные события . Вы можете создавать и запускать пользовательские события, используя функцию socket.emit .
Например, следующий код генерирует событие с именем testerEvent —
var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); app.get('/', function(req, res) { res.sendfile('index.html'); }); io.on('connection', function(socket) { console.log('A user connected'); //Send a message when setTimeout(function() { //Sending an object when emmiting an event socket.emit('testerEvent', { description: 'A custom event named testerEvent!'}); }, 4000); socket.on('disconnect', function () { console.log('A user disconnected'); }); }); http.listen(3000, function() { console.log('listening on localhost:3000'); });
Чтобы обработать это пользовательское событие на клиенте, нам нужен слушатель, который прослушивает событие testerEvent. Следующий код обрабатывает это событие на клиенте —
<!DOCTYPE html> <html> <head> <title>Hello world</title> </head> <script src = "/socket.io/socket.io.js"></script> <script> var socket = io(); socket.on('testerEvent', function(data){document.write(data.description)}); </script> <body>Hello world</body> </html>
Это будет работать так же, как и в нашем предыдущем примере, с событием, являющимся в этом случае testerEvent. Когда вы откроете браузер и перейдете на localhost: 3000, вы увидите:
Hello world
Через четыре секунды это событие будет запущено, и в браузере будет изменен текст на —
A custom event named testerEvent!
Мы также можем отправлять события от клиента. Чтобы отправить событие от вашего клиента, используйте функцию emit объекта сокета.
<!DOCTYPE html> <html> <head> <title>Hello world</title> </head> <script src = "/socket.io/socket.io.js"></script> <script> var socket = io(); socket.emit('clientEvent', 'Sent an event from the client!'); </script> <body>Hello world</body> </html>
Чтобы обработать эти события, используйте функцию on объекта сокета на вашем сервере.
var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); app.get('/', function(req, res) { res.sendfile('index.html'); }); io.on('connection', function(socket) { socket.on('clientEvent', function(data) { console.log(data); }); }); http.listen(3000, function() { console.log('listening on localhost:3000'); });
Итак, теперь, если мы перейдем к localhost: 3000, мы получим пользовательское событие с именем clientEvent . Это событие будет обработано на сервере путем регистрации —
Sent an event from the client!
Socket.IO — Вещание
Вещание означает отправку сообщения всем подключенным клиентам. Вещание может быть сделано на нескольких уровнях. Мы можем отправить сообщение всем подключенным клиентам, клиентам в пространстве имен и клиентам в определенной комнате. Чтобы передать событие всем клиентам, мы можем использовать метод io.sockets.emit .
Примечание. Это отправит событие ВСЕМ подключенным клиентам (событие сокета, который мог запустить это событие).
В этом примере мы передадим количество подключенных клиентов всем пользователям. Обновите файл app.js, чтобы включить следующее.
var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); app.get('/', function(req, res) { res.sendfile('index.html'); }); var clients = 0; io.on('connection', function(socket) { clients++; io.sockets.emit('broadcast',{ description: clients + ' clients connected!'}); socket.on('disconnect', function () { clients--; io.sockets.emit('broadcast',{ description: clients + ' clients connected!'}); }); }); http.listen(3000, function() { console.log('listening on localhost:3000'); });
На стороне клиента нам просто нужно обработать событие широковещания —
<!DOCTYPE html> <html> <head> <title>Hello world</title> </head> <script src = "/socket.io/socket.io.js"></script> <script> var socket = io(); socket.on('broadcast',function(data) { document.body.innerHTML = ''; document.write(data.description); }); </script> <body>Hello world</body> </html>
Если вы подключите четыре клиента, вы получите следующий результат —
Это должно было отправить событие всем. Теперь, если мы хотим отправить событие всем, но клиенту, который вызвал его (в предыдущем примере это было вызвано новыми клиентами при подключении), мы можем использовать socket.broadcast.emit .
Давайте отправим новому пользователю приветственное сообщение и сообщим другим клиентам о его присоединении. Поэтому в вашем файле app.js при подключении клиента отправьте ему приветственное сообщение и передайте номер подключенного клиента всем остальным.
var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); app.get('/', function(req, res) { res.sendfile('index.html'); }); var clients = 0; io.on('connection', function(socket) { clients++; socket.emit('newclientconnect',{ description: 'Hey, welcome!'}); socket.broadcast.emit('newclientconnect',{ description: clients + ' clients connected!'}) socket.on('disconnect', function () { clients--; socket.broadcast.emit('newclientconnect',{ description: clients + ' clients connected!'}) }); }); http.listen(3000, function() { console.log('listening on localhost:3000'); });
И ваш HTML для обработки этого события —
<!DOCTYPE html> <html> <head> <title>Hello world</title> </head> <script src = "/socket.io/socket.io.js"></script> <script> var socket = io(); socket.on('newclientconnect',function(data) { document.body.innerHTML = ''; document.write(data.description); }); </script> <body>Hello world</body> </html>
Теперь новый клиент получает приветственное сообщение, а другие получают количество клиентов, которые в данный момент подключены к серверу.
Socket.IO — Пространства имен
Socket.IO позволяет вам «именовать» свои сокеты, что по сути означает назначение разных конечных точек или путей. Это полезная функция, позволяющая минимизировать количество ресурсов (TCP-соединений) и в то же время разделять проблемы в вашем приложении за счет разделения каналов связи. Несколько пространств имен фактически используют одно и то же соединение WebSockets, что позволяет нам сэкономить порты сокетов на сервере.
Пространства имен создаются на стороне сервера. Однако к ним присоединяются клиенты, отправляя запрос на сервер.
Пространства имен по умолчанию
Корневое пространство имен «/» является пространством имен по умолчанию, к которому присоединяются клиенты, если клиентское пространство не указывает пространство имен при подключении к серверу. Все подключения к серверу с использованием клиентской стороны объекта сокета выполняются в пространстве имен по умолчанию. Например —
var socket = io();
Это подключит клиента к пространству имен по умолчанию. Все события в этом соединении пространства имен будут обрабатываться объектом io на сервере. Все предыдущие примеры использовали пространства имен по умолчанию для связи с сервером и обратно.
Пользовательские пространства имен
Мы можем создать наши собственные пространства имен. Чтобы настроить собственное пространство имен, мы можем вызвать функцию ‘of’ на стороне сервера —
var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); app.get('/', function(req, res) { res.sendfile('index.html'); }); var nsp = io.of('/my-namespace'); nsp.on('connection', function(socket) { console.log('someone connected'); nsp.emit('hi', 'Hello everyone!'); }); http.listen(3000, function() { console.log('listening on localhost:3000'); });
Теперь, чтобы подключить клиента к этому пространству имен, вам необходимо предоставить пространство имен в качестве аргумента для вызова конструктора io, чтобы создать соединение и объект сокета на стороне клиента.
Например, чтобы подключиться к указанному выше пространству имен, используйте следующий HTML —
<!DOCTYPE html> <html> <head> <title>Hello world</title> </head> <script src = "/socket.io/socket.io.js"></script> <script> var socket = io('/my-namespace'); socket.on('hi',function(data) { document.body.innerHTML = ''; document.write(data); }); </script> <body></body> </html>
Каждый раз, когда кто-то подключается к этому пространству имен, он получает событие «привет».
Socket.IO — Номера
В каждом пространстве имен вы также можете определить произвольные каналы, к которым сокеты могут присоединяться и выходить. Эти каналы называются комнатами. Номера используются для дальнейшего разделения проблем. Комнаты также имеют одно и то же сокетное соединение, что и пространства имен. При использовании комнат нужно помнить, что их можно объединять только на стороне сервера.
Соединяющиеся комнаты
Вы можете вызвать метод соединения для сокета, чтобы подписать сокет на данный канал / комнату. Например, давайте создадим комнаты под названием room- <room-number> и присоединимся к некоторым клиентам. Как только эта комната заполнится, создайте другую комнату и присоединитесь к клиентам.
Примечание. В настоящее время мы делаем это в пространстве имен по умолчанию, то есть «/». Вы также можете реализовать это в пользовательских пространствах имен таким же образом.
Чтобы присоединиться к комнате, вам нужно указать имя комнаты в качестве аргумента для вызова функции соединения.
var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); app.get('/', function(req, res) { res.sendfile('index.html'); }); var roomno = 1; io.on('connection', function(socket) { //Increase roomno 2 clients are present in a room. if(io.nsps['/'].adapter.rooms["room-"+roomno] && io.nsps['/'].adapter.rooms["room-"+roomno].length > 1) roomno++; socket.join("room-"+roomno); //Send this event to everyone in the room. io.sockets.in("room-"+roomno).emit('connectToRoom', "You are in room no. "+roomno); }) http.listen(3000, function() { console.log('listening on localhost:3000'); });
Просто обработайте это событие connectToRoom на клиенте.
<!DOCTYPE html> <html> <head> <title>Hello world</title> </head> <script src = "/socket.io/socket.io.js"></script> <script> var socket = io(); socket.on('connectToRoom',function(data) { document.body.innerHTML = ''; document.write(data); }); </script> <body></body> </html>
Теперь, если вы подключите три клиента, первые два получат следующее сообщение —
You are in room no. 1
Последний клиент получит следующее сообщение —
You are in room no. 2
Выходя из комнаты
Чтобы покинуть комнату, вам нужно вызвать функцию выхода так же, как вы вызывали функцию соединения в сокете.
Например — покинуть комнату «комната-1» ,
socket.leave("room-"+roomno);
Socket.IO — Обработка ошибок
До сих пор мы работали на локальных серверах, что почти никогда не даст нам ошибок, связанных с соединениями, тайм-аутами и т. Д. Однако в реальных производственных средах обработка таких ошибок имеет первостепенное значение. Поэтому сейчас мы обсудим, как мы можем обрабатывать ошибки подключения на стороне клиента.
Клиентский API предоставляет нам следующие встроенные события —
-
Connect — когда клиент успешно подключается.
-
Подключение — когда клиент находится в процессе подключения.
-
Отключить — когда клиент отключен.
-
Connect_failed — при сбое соединения с сервером.
-
Ошибка — сообщение об ошибке отправлено с сервера.
-
Сообщение — когда сервер отправляет сообщение, используя функцию отправки .
-
Переподключение — когда переподключение к серверу прошло успешно.
-
Переподключение — когда клиент находится в процессе подключения.
-
Reconnect_failed — когда попытка переподключения не удалась.
Connect — когда клиент успешно подключается.
Подключение — когда клиент находится в процессе подключения.
Отключить — когда клиент отключен.
Connect_failed — при сбое соединения с сервером.
Ошибка — сообщение об ошибке отправлено с сервера.
Сообщение — когда сервер отправляет сообщение, используя функцию отправки .
Переподключение — когда переподключение к серверу прошло успешно.
Переподключение — когда клиент находится в процессе подключения.
Reconnect_failed — когда попытка переподключения не удалась.
Для обработки ошибок мы можем обрабатывать эти события, используя объект out-socket, который мы создали на нашем клиенте.
Например, если у нас не удается установить соединение, мы можем использовать следующий код для повторного подключения к серверу.
socket.on('connect_failed', function() { document.write("Sorry, there seems to be an issue with the connection!"); })
Socket.IO — ведение журнала и отладка
Socket.IO использует очень известный модуль отладки, разработанный основным автором ExpresJS, который называется debug . Ранее Socket.IO регистрировал все на консоли, что затрудняло отладку проблемы. После выпуска v1.0 вы можете указать, что вы хотите войти.
Серверный
Лучший способ узнать, какая информация доступна — это использовать * —
DEBUG=* node app.js
Это раскрасит и выведет все, что происходит с консолью вашего сервера. Например, мы можем рассмотреть следующий скриншот.
Сторона клиента
Вставьте это в консоль, нажмите Enter и обновите страницу. Это снова выведет все, что связано с Socket.io на вашу консоль.
localStorage.debug = '*';
Вы можете ограничить вывод, чтобы получить отладочную информацию с входящими данными из сокета, используя следующую команду.
localStorage.debug = 'socket.io-client:socket';
Вы можете увидеть результат, как на следующем скриншоте, если вы используете второй оператор для регистрации информации —
Здесь очень хорошая запись в блоге, связанная с отладкой socket.io .
Socket.IO — Внутренние устройства
В этой главе мы обсудим резервные соединения, подключение с помощью Socket.IO, события и сообщения.
откаты
Socket.IO имеет множество базовых транспортных механизмов, которые имеют дело с различными ограничениями, возникающими из-за проблем с браузерами, реализаций WebSocket, брандмауэров, блокировки портов и т. Д.
Хотя W3C имеет определенную спецификацию для WebSocket API, он все еще не реализован. Socket.IO предоставляет нам запасные механизмы, которые могут справиться с такими проблемами. Если мы разрабатываем приложения с использованием нативного API, мы должны сами реализовать запасные варианты. Socket.IO охватывает большой список запасных вариантов в следующем порядке:
- WebSockets
- FlashSocket
- XHR длинный опрос
- XHR многочастная потоковая передача
- XHR опрос
- JSONP опрос
- плавающие фреймы
Подключение через Socket.IO
Соединение Socket.IO начинается с рукопожатия. Это делает рукопожатие особой частью протокола. Помимо рукопожатия, все другие события и сообщения в протоколе передаются через сокет.
Socket.IO предназначен для использования с веб-приложениями, и поэтому предполагается, что эти приложения всегда смогут использовать HTTP. Именно по этой причине рукопожатие Socket.IO происходит по HTTP с использованием запроса POST на URI рукопожатия (передается в метод connect).
События и сообщения
Собственный API WebSocket отправляет только сообщения. Socket.IO предоставляет дополнительный слой над этими сообщениями, который позволяет нам создавать события и снова помогает нам легко разрабатывать приложения, разделяя различные типы отправляемых сообщений.
Собственный API отправляет сообщения только в виде простого текста. Об этом также заботится Socket.IO. Он обрабатывает сериализацию и десериализацию данных для нас.
У нас есть официальный клиентский API для Интернета. Для других клиентов, таких как собственные мобильные телефоны, другие клиенты приложений, мы также можем использовать Socket.IO, выполнив следующие шаги.
Шаг 1 — Соединение должно быть установлено с использованием того же протокола соединения, который обсуждался выше.
Шаг 2 — Сообщения должны быть в том же формате, который указан Socket.IO. Этот формат позволяет Socket.IO определять тип сообщения и данные, отправляемые в сообщении, а также некоторые метаданные, полезные для работы.
Формат сообщения —
[type] : [id ('+')] : [endpoint] (: [data]
Параметры в приведенной выше команде объяснены ниже —
-
Тип представляет собой однозначное целое число, определяющее тип сообщения.
-
ID — это идентификатор сообщения, инкрементное целое число, используемое для подтверждений.
-
Конечная точка — это конечная точка сокета, которой сообщение предназначено для доставки …
-
Данные — это связанные данные, которые будут доставлены в сокет. В случае сообщений он обрабатывается как обычный текст, для других событий он обрабатывается как JSON.
Тип представляет собой однозначное целое число, определяющее тип сообщения.
ID — это идентификатор сообщения, инкрементное целое число, используемое для подтверждений.
Конечная точка — это конечная точка сокета, которой сообщение предназначено для доставки …
Данные — это связанные данные, которые будут доставлены в сокет. В случае сообщений он обрабатывается как обычный текст, для других событий он обрабатывается как JSON.
В следующей главе мы напишем приложение для чата в Socket.IO.
Socket.IO — приложение для чата
Теперь, когда мы хорошо знакомы с Socket.IO, давайте напишем приложение для чата, которое мы можем использовать для общения в разных чатах. Мы позволим пользователям выбирать имя пользователя и разрешать им общаться в чате, используя их. Итак, во-первых, давайте настроим наш HTML-файл для запроса имени пользователя —
<!DOCTYPE html> <html> <head> <title>Hello world</title> </head> <script src = "/socket.io/socket.io.js"></script> <script> var socket = io(); </script> <body> <input type = "text" name = "name" value = "" placeholder = "Enter your name!"> <button type = "button" name = "button">Let me chat!</button> </body> </html>
Теперь, когда мы настроили наш HTML на запрос имени пользователя, давайте создадим сервер для приема соединений от клиента. Мы позволим людям отправлять выбранные имена пользователей с помощью события setUsername . Если пользователь существует, мы ответим на событие userExists , иначе используя событие userSet .
var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); app.get('/', function(req, res) { res.sendfile('index.html'); }); users = []; io.on('connection', function(socket) { console.log('A user connected'); socket.on('setUsername', function(data) { if(users.indexOf(data) > -1) { users.push(data); socket.emit('userSet', {username: data}); } else { socket.emit('userExists', data + ' username is taken! Try some other username.'); } }) }); http.listen(3000, function() { console.log('listening on localhost:3000'); });
Нам нужно отправить имя пользователя на сервер, когда люди нажимают на кнопку. Если пользователь существует, мы показываем сообщение об ошибке; иначе мы показываем экран обмена сообщениями —
<!DOCTYPE html> <html> <head> <title>Hello world</title> </head> <script src = "/socket.io/socket.io.js"></script> <script> var socket = io(); function setUsername() { socket.emit('setUsername', document.getElementById('name').value); }; var user; socket.on('userExists', function(data) { document.getElementById('error-container').innerHTML = data; }); socket.on('userSet', function(data) { user = data.username; document.body.innerHTML = '<input type = "text" id = "message">\ <button type = "button" name = "button" onclick = "sendMessage()">Send</button>\ <div id = "message-container"></div>'; }); function sendMessage() { var msg = document.getElementById('message').value; if(msg) { socket.emit('msg', {message: msg, user: user}); } } socket.on('newmsg', function(data) { if(user) { document.getElementById('message-container').innerHTML += '<div><b>' + data.user + '</b>: ' + data.message + '</div>' } }) </script> <body> <div id = "error-container"></div> <input id = "name" type = "text" name = "name" value = "" placeholder = "Enter your name!"> <button type = "button" name = "button" onclick = "setUsername()"> Let me chat! </button> </body> </html>
Теперь, если вы подключите два клиента с одним и тем же именем пользователя, появится сообщение об ошибке, как показано на скриншоте ниже.
После того, как вы предоставили приемлемое имя пользователя, вы попадете на экран с окном сообщений и кнопкой для отправки сообщений. Теперь мы должны обработать и направить сообщения подключенному клиенту. Для этого измените файл app.js, включив в него следующие изменения:
var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); app.get('/', function(req, res) { res.sendfile('index.html'); }); users = []; io.on('connection', function(socket) { console.log('A user connected'); socket.on('setUsername', function(data) { console.log(data); if(users.indexOf(data) > -1) { socket.emit('userExists', data + ' username is taken! Try some other username.'); } else { users.push(data); socket.emit('userSet', {username: data}); } }); socket.on('msg', function(data) { //Send message to everyone io.sockets.emit('newmsg', data); }) }); http.listen(3000, function() { console.log('listening on localhost:3000'); });
Теперь подключите любое количество клиентов к вашему серверу, предоставьте им имя пользователя и начните общаться! В следующем примере мы связали двух клиентов с именами Ayush и Harshit и отправили несколько сообщений от обоих клиентов: