Введение в Web Sockets API

Сокеты Web позволяют приложению передавать информацию между сервером и браузером, а не опрашивать сервер с заданным интервалом времени или использовать нестандартные приемы с помощью <iframe> — это позволяет разработчикам web уменьшить ненужный трафик HTTP и сложность программирования.

Сокеты Web отключены по умолчанию в связи со спецификацией связанной с проблемами безопасности. Тем не менее, можно включить их в браузере Opera с помощью opera:config#UserPrefs|EnableWebSockets.




Я думаю, что работа над сокетами Web (TCPConnection в то время) предшествовала моим мыслям об управлении моим макетом поезда с помощью сокетов Web, но сокеты Web несомненно могли бы сделать это намного легче. Проблема состоит в том, что обычное приложение Web управляет одиночной системой: имеется один компьютер, соединенный через последовательный порт с устройством Marklin Interface, и требуется написать страницу Web, которая взаимодействует с этим компьютером, посылает инструкции и получает обновления, не опрашивая, имеет несколько соединений, использует потоки <script> в <iframe> и т.д.

API сокетов Web позволяет открывать соединение с сервером, используя новый протокол ws, который остается открытым в течение времени жизни сеанса. Он является полнодуплексным, т.е. допускает коммуникацию в обоих направлениях одновременно. Он также имеет значительно меньшие накладные расходы, чем повторяющиеся обращения к серверу для отслеживания изменений. Раньше такие функции были доступны только с помощью технологии плагинов типа Flash.


Сокеты Web включают в себя API JavaScript, описанный ниже, и протокол ws: — или wss: для шифрованной передачи. Протокол стандартизован в IETF и может изменяться; однако изменение API маловероятно.

API сокетов Web

Для соединения с сервером сокета Web, используется конструктор WebSocket следующим образом:

var ws = new WebSocket('ws://example.org:12345/demo');

Можно также запросить специальные субпротоколы с помощью второго параметра:

var ws = new WebSocket('ws://example.org:12345/demo', 'my-chat-protocol');

Если требуется более одного субпротокола, можно передать их в массиве строк (будет поддерживаться в будущей версии браузера Opera):

var ws = new WebSocket('ws://example.org:12345/demo', ['chat-protocol-v2-with-bells-and-whistles', 'chat-protocol']);

Сервер будет выбирать наиболее совместимую версию, которую можно затем проверить, считывая свойство ws.protocol.

Можно пытаться соединиться с любым хостом и любым портом, за исключением блокированных портов, однако сервер должен поддерживать сокеты Web и будет ожидать соединение от определенной страницы, которая, как ожидается, открывает соединение. Субпротокол, если используется, является произвольной строкой (состоящей из печатных символов ASCII), которая гарантирует, что клиент и сервер посылают сообщения, которые являются взаимно понятными. Например, Caucho Technology (http://blog.caucho.com/?p=500) пишет, что субпротоколы полезны "чтобы гарантировать, что клиент Quake/2.0 [WebSocket] не будет путаться, общаясь с сервером Quake/1.0 [WebSocket]".

Если соединение установлено, объект WebSocket получает событие open, и после этого можно начинать отправлять и получать сообщения. В контексте сокетов Web, сообщение является просто строкой текста, например, в формате JSON. Вы посылаете сообщение с помощью метода send(), и обрабатываете входящие сообщения с помощью перехватчика событий onmessage:

ws.onopen = function(e) {
// соединение теперь установлено 
// давайте пошлем простое сообщение 
this.send('{"username": "Bruce", "message": "Hello!"}');
}
ws.onmessage = function(e) {
// получить сообщение с сервера 
var msg = JSON.parse(e.data);
alert(msg.message);
}

Если сервер отказывает в соединении, или если соединение закрывается по какой-то причине, объект WebSocket получает сообщение close.

ws.onclose = function(e) {
alert('WebSocket closed :-(');
}

Соединение можно закрыть с помощью метода close():

ws.close();

Если сервер посылает кадры, которые браузер не понимает (может быть потому что сервер поддерживает только более новую версию протокола), то вы получите событие error. Если вы получаете события error, но не события message, вы можете попробовать закрыть соединение и вернуться к использованию другого средства, например, длинные опросы XHR или сервер Comet.

Функция обнаружения сокетов Web устроена просто — выполните следующее:

if ('WebSocket' in window) {
// Сокеты Web поддерживаются 
} else {
// Сокеты Web не поддерживаются 
}

Или если вы уже используете Modernizr в своем приложении, то обнаружение будет таким же простым:

if (Modernizr.websockets) {
// Сокеты Web поддерживаются 
} else {
// Сокеты Web не поддерживаются 
}

Как быть в случае неподдерживающих сокеты Web браузеров?

Вики HTML5 Cross browser Polyfills перечисляет три сценария, которые можно использовать в качестве средства симуляции сокетов Web для более старых, неподдерживающих сокеты Web браузеров (отметим, что мы не проверяли все такие браузеры). Проект Socket.IO является особенно хорошим решением, так как он соединяет сервер сокета Web Node.js с унифицированным, абстрактным API с автоматическим откатом к сокетам Flash, длинному опросу AJAX, многокомпонентному потоковому AJAX, потоковому <iframe> и JSONP для более слабых клиентов. Socket.IO распространяется с открытым исходным кодом и работает с Node.js, с несколькими другими совместимыми реализациями для других серверных технологий.

Демонстрация

Следующие приложения используют сокеты Web для предоставления многопользовательского взаимодействия (почти) в реальном времени:
  • Mr. Doob's Multiuser Sketchpad: В этом многопользовательском приложении рисования с помощью <canvas>, сокеты Web используются для передачи координат линий, которые другие пользователи рисуют на каждом клиенте как получится.
  • Rumpetroll: В качестве головастика вы можете плавать и общаться с другими головастиками. Сокеты Web предназначены для определения местонахождения головастиков и сообщений, которые передаются каждому пользователю.
  • wordsquared.com: В этой многопользовательской сетевой игре со словами сокеты Web используются, чтобы пользователи видели карточки других игроков во время игры.
Кроме этих демонстраций Ericsson Labs имеет интересный видеофильм, демонстрирующий преимущества сокетов Web по сравнению с длинными опросами HTTP для приложений реального времени:

Ресурсы


Тест

Свойство fillStyle позволяет:
(Отметьте один правильный вариант ответа.)
Вариант 1 рисовать заполненные прямоугольники
Вариант 2 задать цвет для штрихов изображения
Вариант 3 задать цвет для изображения заполненных фигур

Свойство strokeRect позволяет:
(Отметьте один правильный вариант ответа.)
Вариант 1 рисовать прямоугольники без заливки, но с обводкой
Вариант 2 очистить некоторую часть холста
Вариант 3 рисовать прямоугольники со сплошной заливкой

Сколько аргументов принимает метод fillRect()?
(Отметьте один правильный вариант ответа.)
Вариант 1 четыре
Вариант 2 один
Вариант 3 два
Вариант 4 три

Цвет заливки и обводки элементов можно задать в форматах:
(Ответ считается верным, если отмечены все правильные варианты ответов.)
Вариант 1 rgba()
Вариант 2 cmyk()
Вариант 3 rgb()

Какой метод позволяет начать рисование фигуры, задаваемой с помощью пути:
(Отметьте один правильный вариант ответа.)
Вариант 1 goPath()
Вариант 2 startPath()
Вариант 3 beginPath()

Какой метод позволяет вставить другие изображения в контекст холста?
(Отметьте один правильный вариант ответа.)
Вариант 1 drawimage()
Вариант 2 getimage()
Вариант 3 addimage()

В каком объекте хранятся пиксели изображения при использовании методов createImageData(), getImageData() и putImageData()?
(Отметьте один правильный вариант ответа.)
Вариант 1 DataImage
Вариант 2 ImageData
Вариант 3 ImgData

Какой объект должен поддерживаться клиентским приложением для работы с сокетами?
(Отметьте один правильный вариант ответа.)
Вариант 1 WebSocket
Вариант 2 Sockets
Вариант 3 HtmlSocket

Как можно обратиться к серверу с помощью конструктора сокетов:
(Отметьте один правильный вариант ответа.)
Вариант 1 var ws = new WebSocket('ws://code.org:12345/demo’);
Вариант 2 var ws = new WebSocket('ws:www.code.org:12345/demo’);
Вариант 3 var ws = new WebSocket('ws:code.org:12345/demo’);

С помощью какого перехватчика событий можно на клиентском компьютере обрабатывать посланные сервером сообщения?
(Отметьте один правильный вариант ответа.)
Вариант 1 onload
Вариант 2 onsend
Вариант 3 onmessage

С помощью какого метода объект WebSocket может разорвать соединение с сервером?
(Отметьте один правильный вариант ответа.)
Вариант 1 abort()
Вариант 2 exit()
Вариант 3 close()

Какое событие произойдет, если браузер получит кадры от сервера в непонятном для него формате?
(Отметьте один правильный вариант ответа.)
Вариант 1 error
Вариант 2 close
Вариант 3 message