Статьи

WebSockets: стабильный и готовый для разработчиков

WebSockets стабильны и готовы для разработчиков, чтобы начать создавать инновационные приложения и сервисы. Это руководство представляет собой простое введение в W3C WebSocket API и его базовый протокол WebSocket . Обновленная демонстрация Flipbook использует последнюю версию API и протокола.

Рабочие группы добились значительных успехов, и API-интерфейс WebSocket является рекомендацией кандидата W3C. Internet Explorer 10 реализует эту версию спецификации. Вы можете узнать об эволюции спецификации здесь .

WebSockets позволяют веб-приложениям доставлять уведомления и обновления в режиме реального времени в браузере. Разработчики столкнулись с проблемами при обходе ограничений в исходной модели браузера HTTP-запрос-ответ, которая не была разработана для сценариев реального времени. WebSockets позволяют браузерам открывать двунаправленный, дуплексный канал связи со службами. Каждая сторона может затем использовать этот канал для немедленной отправки данных другой. Теперь сайты от социальных сетей и игр до финансовых сайтов могут предоставлять лучшие сценарии в реальном времени, в идеале с использованием одной и той же разметки в разных браузерах.

Введение в API WebSocket с использованием примера Echo

Приведенные ниже фрагменты кода используют простой эхо-сервер, созданный с использованием пространства имен ASP.NET System.Web.WebSockets, для отображения текстовых и двоичных сообщений, отправляемых из приложения. Приложение позволяет пользователю вводить текст для отправки и возвращать его как текстовое сообщение, или рисовать картинку, которую можно отправлять и возвращать как двоичное сообщение.

Более сложный пример, который позволяет вам экспериментировать с задержками и различиями в производительности между WebSockets и HTTP-опросом, см. В демонстрационной версии Flipbook .

Детали подключения к серверу WebSocket

Это простое объяснение основано на прямой связи между приложением и сервером. Если прокси-сервер настроен, то IE10 запускает процесс, отправляя HTTP-запрос CONNECT на прокси-сервер.

При создании объекта WebSocket между клиентом и сервером происходит обмен рукопожатием для установления соединения WebSocket.

IE10 запускает процесс, отправляя HTTP-запрос на сервер:

  GET / echo HTTP / 1.1
 Хост: example.microsoft.com
 Обновление: websocket
 Подключение: Обновление
 Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ ==
 Происхождение: http://microsoft.com
 Sec-WebSocket-версия: 13 

Давайте посмотрим на каждую часть этого запроса. Процесс подключения начинается со стандартного HTTP-запроса GET, который позволяет ему проходить через брандмауэры, прокси-серверы и других посредников:

  GET / echo HTTP / 1.1
 Хост: example.microsoft.com 

Заголовок HTTP Upgrade запрашивает, чтобы сервер переключил протокол уровня приложения с HTTP на протокол WebSocket.

  Обновление: websocket
 Подключение: Обновление 

Сервер преобразует значение в заголовке Sec-WebSocket-Key в своем ответе, чтобы продемонстрировать, что он понимает протокол WebSocket:

  Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ == 

Заголовок Origin устанавливается IE10, чтобы позволить серверу обеспечивать безопасность на основе источника.

  Происхождение: http://microsoft.com 

Заголовок Sec-WebSocket-Version идентифицирует запрашиваемую версию протокола. Версия 13 является окончательной версией в предлагаемом стандарте IETF:

  Sec-WebSocket-версия: 13 

Если сервер принимает запрос на обновление протокола уровня приложения, он возвращает ответ HTTP 101 Switching Protocols:

  HTTP / 1.1 101 протоколы коммутации
 Обновление: websocket
 Подключение: Обновление 

Чтобы продемонстрировать, что он понимает протокол WebSocket, сервер выполняет стандартизированное преобразование Sec-WebSocket-Key из запроса клиента и возвращает результаты в заголовке Sec-WebSocket-Accept:

  Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK + xOo = 

Затем IE10 сравнивает Sec-WebSocket-Key с Sec-WebSocket-Accept для проверки того, что сервер является сервером WebSocket, а не HTTP-сервером с манией величия.

Рукопожатие клиента установило соединение HTTP-на-TCP между IE10 и сервером. После того, как сервер вернет свой ответ 101, протокол уровня приложения переключается с HTTP на WebSockets, который использует ранее установленное TCP-соединение.

На этом этапе HTTP полностью отсутствует. Используя облегченный проводной протокол WebSocket, теперь сообщения могут быть отправлены или получены любой конечной точкой в ​​любое время.

Программирование подключения к серверу WebSocket

Протокол WebSocket определяет две новые схемы URI, которые похожи на схемы HTTP.

  • «Ws:» «//» host [«:» port] path [«?» Query] смоделирован по схеме «http:». Порт по умолчанию — 80. Он используется для незащищенных (незашифрованных) соединений.
  • «Wss:» «//» host [«:» port] path [«?» Query] смоделирован по схеме «https:». Порт по умолчанию — 443. Он используется для безопасных соединений, проходящих через Transport Layer Security .

Когда присутствуют прокси или сетевые посредники, существует более высокая вероятность того, что безопасные соединения будут успешными, поскольку посредники менее склонны пытаться преобразовать безопасный трафик.

Следующий фрагмент кода устанавливает соединение WebSocket:

  var host = "ws: //example.microsoft.com";
 var socket = новый WebSocket (хост); 

ReadyState — Готов… Установить… Иди…

Атрибут WebSocket.readyState представляет состояние соединения: СОЕДИНЯЕТСЯ, ОТКРЫТО, ЗАКРЫТО или ЗАКРЫТО. Когда WebSocket создается впервые, для readyState устанавливается значение CONNECTING. Когда соединение установлено, readyState устанавливается в положение OPEN. Если не удается установить соединение, то для readyState устанавливается значение ЗАКРЫТО.

Регистрация на открытые мероприятия

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

  socket.onopen = function (openEvent) {
 document.getElementById ("serverStatus"). innerHTML = 'Состояние веб-сокета ::' + 'OPEN';
 }; 

Подробности отправки и получения сообщений

После успешного установления связи приложение и сервер Websocket могут обмениваться сообщениями WebSocket. Сообщение состоит из последовательности одного или нескольких фрагментов сообщения или «кадров» данных.

Каждый кадр включает в себя информацию, такую ​​как:

  • Длина кадра
  • Тип сообщения (двоичное или текстовое) в первом кадре сообщения
  • Флаг (FIN), указывающий, является ли это последний кадр в сообщении

IE10 собирает фреймы в полное сообщение перед передачей его в скрипт.

Программирование отправки и получения сообщений

API send ArrayBuffers или Blobs.

Например, этот фрагмент кода извлекает текст, введенный пользователем, и отправляет его на сервер в виде текстового сообщения UTF-8, которое необходимо отправить обратно. Он проверяет, что Websocket находится в OPEN readyState:

 function sendTextMessage () {
	 if (socket.readyState! = WebSocket.OPEN)
		 возвращение;
	 var e = document.getElementById ("textmessage");
	 socket.send (e.value);
 }

Этот фрагмент извлекает изображение, нарисованное пользователем на холсте, и отправляет его на сервер в виде двоичного сообщения:

 function sendBinaryMessage () {
	 if (socket.readyState! = WebSocket.OPEN)
		 возвращение;
	 var sourceCanvas = document.getElementById ('source');
	 // msToBlob возвращает объект blob из изображения или рисунка холста
	 socket.send (sourceCanvas.msToBlob ());
	 // ...
 }

Регистрация для сообщений событий

Чтобы получать сообщения, приложение должно зарегистрироваться для сообщений о событиях. Обработчик события получает MessageEvent, который содержит данные в MessageEvent.data. Данные могут быть получены в виде текстовых или двоичных сообщений.

При получении двоичного сообщения атрибут WebSocket.binaryType определяет, будут ли данные сообщения возвращены в виде типа BLOB-объекта или типа ArrayBuffer. Атрибут может быть установлен как «blob» или «arraybuffer». В примерах ниже используется значение по умолчанию «blob».

Этот фрагмент получает отраженное изображение или текст с сервера веб-сокетов. Если данные являются BLOB-объектами, то изображение возвращается и рисуется на целевом холсте;
в противном случае текстовое сообщение UTF-8 было возвращено и отображается в текстовом поле.

 socket.onmessage = function (messageEvent) {
	 if (messageEvent.data instanceof Blob) {
		 var destinationCanvas = document.getElementById ('destination');
		 var destinationContext = destinationCanvas.getContext ('2d');
		 var image = new Image ();
		 image.onload = function () {
			 destinationContext.clearRect (0, 0, destinationCanvas.width, destinationCanvas.height);
			 destinationContext.drawImage (image, 0, 0);
		 }
		 image.src = URL.createObjectURL (messageEvent.data);
	 } еще {
		 document.getElementById ("textresponse"). value = messageEvent.data;
	 }
 }; 

Подробная информация о закрытии соединения WebSocket

Подобно открывающему рукопожатию, есть закрывающее рукопожатие. Любая конечная точка (приложение или сервер) может инициировать это рукопожатие.
Специальный вид кадра — закрытый кадр — отправляется на другую конечную точку. Фрейм закрытия может содержать необязательный код состояния и причину закрытия. Протокол определяет набор соответствующих значений для кода состояния. Отправитель закрытого кадра не должен отправлять дополнительные данные приложения после закрытого кадра.
Когда другая конечная точка получает закрытый кадр, она отвечает своим собственным закрывающим кадром в ответ. Он может отправлять ожидающие сообщения, прежде чем ответить закрывающим фреймом.

Программирование закрытия WebSocket и регистрация для закрытия событий

Приложение инициирует рукопожатие при открытом соединении с API закрытия:

  socket.close (1000, «нормальное закрытие»); 

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

 socket.onclose = function (closeEvent) {
	 document.getElementById ("serverStatus"). innerHTML = 'Состояние веб-сокета ::' + 'CLOSED';
 }; 

API закрытия принимает два необязательных параметра: код состояния, определенный протоколом, и описание. Код состояния должен быть либо 1000, либо в диапазоне от 3000 до 4999. При выполнении закрытия для атрибута readyState устанавливается значение ЗАКРЫТИЕ. После того, как IE10 получает ответ закрытия от сервера, атрибут readyState устанавливается в значение CLOSED и запускается событие закрытия.

Использование Fiddler для просмотра трафика WebSockets

Fiddler — это популярный прокси-сервер отладки HTTP. В последних версиях есть поддержка протокола WebSocket. Вы можете проверить обмен заголовками в рукопожатии WebSocket:

Все сообщения WebSocket также регистрируются. На скриншоте ниже вы можете видеть, что «спираль» была отправлена ​​на сервер в виде текстового сообщения UTF-8 и отозвана обратно:

Вывод

Если вы хотите узнать больше о WebSockets, вы можете посмотреть эти сессии на конференции Microsoft // Build / с сентября 2011 года:

Если вам интересно использовать технологии Microsoft для создания службы WebSocket, эти сообщения являются хорошим введением:

Начните разработку с WebSockets сегодня!
Изображение электрической розетки через Shutterstock