Подключение к веб сокетам

Обновлено: 04.07.2024

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

Краткая история веб-приложений реального времени

Интернет был построен на представлении о том, что забота браузера– запрос данных с сервера, а забота сервера – обслуживание этих запросов. Эта парадигма не подвергалась сомнению несколько лет. Но с появлением AJAX в 2005 году многие начали работать над созданием двунаправленных соединений.

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

Как работают веб-сокеты

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

Вот упрощённый пример первоначальных заголовков запроса.

Если сервер поддерживает протокол WebSocket, он сообщает об этом с помощью заголовка Upgrade в ответе.

Date : Wed, 16 Oct 2013 10:07:34 GMT

Создаём демо-пример

Создаём демо-пример

Создание приложения на основе веб-сокетов

Мы создадим простое приложение, которое соединяется с сервером по веб-сокету. Перед тем, как мы углубимся в детали API, нужно создать несколько файлов.

Посмотреть на CodePen

Создайте файл index.html и добавьте в него следующую разметку.

Файл style.css , на который ссылается этот код, находится в архиве для загрузки. Далее создадим файл app.js и добавим в него следующий код.

Мы создали несколько переменных и инициализировали их ссылками на ключевые элементы страницы.

Открытие соединений

Теперь, когда готов костяк приложения, можно начать изучать WebSocket API. Для начала узнаем, как создать новое соединение WebSocket. Для этого нужно вызвать конструктор класса WebSocket и передать ему URL сервера.

Скопируйте следующий код в файл app.js , чтобы создать новое соединение.

Добавьте следующий код в файл app.js .

Также мы добавляем класс open элементу <div> .

Обработка ошибок

Обработка ошибок осуществляется через событие error . Добавьте следующий код, который будет записывать ошибки в консоль.

Можно отправлять как текст, так и двоичные данные. В нашем приложении нужно передавать содержимое текстового поля на сервер при отправке формы. Чтобы сделать это, надо определить обработчик события отправки формы.

Добавьте следующий код в файл app.js .

Чтобы добиться этого, скопируйте следующий код в файл app.js .

Закрытие соединений

Когда вы закончите работу с веб-сокетом, нужно разорвать соединение, используя метод close() .

После того, как соединение будет разорвано, браузер вызовет событие close . Добавление обработчика события close позволит выполнить любую «уборку», которая потребуется.

Теперь нам нужно обновить статус соединения при его разрыве. Добавьте следующий код в файл app.js :

Чтобы завершить приложение, нужно добавить обработчик события, который будет вызываться при нажатии кнопки «Close Connection». Он должен вызывать метод close() объекта WebSocket.

Наше приложение готово!

Мониторинг трафика веб-сокета с помощью инструментов для разработчиков в Chrome

«Инструменты разработчика», доступные в браузере Google Chrome включают в себя средства для мониторинга трафика. Чтобы использовать этот инструмент:

  • Откройте «Инструменты разработчика».
  • Перейдите на вкладку Network.
  • Кликните по записи, соответствующей вашему соединению по веб-сокету.
  • Перейдите на вкладку Frames.

Эти инструменты предоставляют общую информацию о данных, переданных через соединение.

WebSocket на сервере

В этой статье мы сфокусировали внимание на том, как использовать веб-сокеты на стороне клиента. Если вы хотите создать собственный сервер WebSocket, существует множество библиотек, которые могут в этом помочь. Одна из наиболее популярных – socket.io , библиотека Node.JS.

  • C++: libwebsockets ;
  • Erlang: Shirasu.ws ;
  • Java: Jetty ;
  • Node.JS: ws ;
  • Ruby: em-websocket ;
  • Python: Tornado , pywebsocket ;
  • PHP: Ratchet , phpws .

Поддержка браузерами

Веб-сокеты поддерживаются практически во всех современных браузерах. Единственными исключениями являются Android- браузеры и Opera Mini.

Заключительные мысли

В этой статье вы узнали о протоколе WebSocket. А также том, как использовать его API для создания веб-приложений, работающих в режиме реального времени.

WebSocket – это большой шаг в эволюции интернета. Возможность создания соединения с низкими затратами ресурсов открывает путь к новому поколению веб-приложений.

Дайте знать, что вы думаете по этой теме статьи в комментариях. Мы крайне благодарны вам за ваши комментарии, дизлайки, отклики, подписки, лайки!

Пожалуйста, оставьте свои отзывы по текущей теме материала. Мы очень благодарим вас за ваши комментарии, подписки, дизлайки, лайки, отклики!

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

Защита подключения с помощью TLS/SSL

В большинстве случаев необходимо использовать безопасное подключение WebSocket, чтобы зашифровать отправляемые и получаемые данные. Это также увеличивает шансы успешного подключения, так как многие посредники, такие как брандмауэры и прокси-серверы, отклоняют незашифрованные подключения WebSocket. Протокол WebSocket определяет эти две схемы URI.

Схема универсального кода ресурса (URI) Цель
wss: Используется для защищенных соединений, которые должны быть зашифрованы.
ws: Используется для незашифрованных соединений.

Чтобы зашифровать подключение WebSocket, воспользуйтесь схемой URI wss: . Ниже приведен пример.

Использование сокета MessageWebSocket для подключения

Обработка событий MessageWebSocket.MessageReceived и MessageWebSocket.Closed

Как показано в приведенном выше примере, до установки подключения и отправки данных с помощью MessageWebSocket необходимо подписаться на события MessageWebSocket.MessageReceived и MessageWebSocket.Closed.

Событие MessageReceived создается при получении данных. Доступ к данным осуществляется через MessageWebSocketMessageReceivedEventArgs. Событие Closed создается, когда клиент или сервер закрывает сокет.

Отправка данных в MessageWebSocket

После установки подключения можно отправлять данные на сервер. Это можно сделать с помощью свойства MessageWebSocket.OutputStream и DataWriter для записи данных.

Примечание. DataWriter становится владельцем потока вывода. Когда DataWriter выходит за пределы области, если к нему прикреплен поток вывода, DataWriter освобождает поток вывода. После этого все последующие попытки использовать поток вывода будут неудачными со значением HRESULT 0x80000013. Но можно вызвать метод DataWriter.DetachStream, чтобы отсоединить поток вывода от DataWriter и вернуть владение потоком событию MessageWebSocket.

Использование StreamWebSocket для подключения

Обработка события StreamWebSocket.Closed

Прежде чем устанавливать подключение и отправлять данные с помощью StreamWebSocket, необходимо подписаться на событие StreamWebSocket.Closed. Событие Closed создается, когда клиент или сервер закрывает сокет.

Отправка данных в StreamWebSocket

После установки подключения можно отправлять данные на сервер. Это можно сделать с помощью свойства StreamWebSocket.OutputStream и DataWriter для записи данных.

Примечание. Если вы хотите записать больше данных в один сокет, не забудьте вызвать метод DataWriter.DetachStream, чтобы отсоединить поток вывода от DataWriter до того, как DataWriter выйдет за пределы области. В результате владельцем потока становится MessageWebSocket.

Получение данных в StreamWebSocket

Дополнительные параметры для MessageWebSocket и StreamWebSocket

Прежде чем устанавливать подключение, можно задать дополнительные параметры в сокете, задав свойства в MessageWebSocketControl или StreamWebSocketControl. Вы осуществляете доступ к экземпляру этих классов из самого объекта сокета через его свойство MessageWebSocket.Control или StreamWebSocket.Control в зависимости от ситуации.

Вот пример использования StreamWebSocket. Такая же схема применяется к MessageWebSocket.

Примечание. Не пытайтесь изменить свойство элемента управления после вызова ConnectAsync. Единственное исключение из этого правила — MessageWebSocketControl.MessageType.

Классы информации WebSocket

MessageWebSocket и StreamWebSocket имеют соответствующий класс, который обеспечивает дополнительную информацию об объекте.

MessageWebSocketInformation предоставляет информацию о MessageWebSocket, и вы извлекаете его экземпляр с помощью свойства MessageWebSocket.Information.

StreamWebSocketInformation предоставляет информацию о StreamWebSocket, и вы извлекаете его экземпляр с помощью свойства StreamWebSocket.Information.

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

Обработка исключений

Ошибка, обнаруженная в операции MessageWebSocket или StreamWebSocket, возвращается в виде значения HRESULT. Можно передать значение HRESULT методу WebSocketError.GetStatus, чтобы преобразовать его в значение перечисления WebErrorStatus.

Для ошибок при проверке параметров можно использовать также значение HRESULT из исключения, чтобы получить подробные сведения об ошибке. Возможные значения HRESULT перечислены в Winerror.h , который находится в вашей установке SDK (например, в папке C:\Program Files (x86)\Windows Kits\10\Include\<VERSION>\shared ). Для многих ошибок при проверке параметров HRESULT возвращает значение E_INVALIDARG.

Назначение времени ожидания при выполнении операций с WebSocket

Чтобы ускорить реакцию приложения и свести эти проблемы к минимуму, можно задать более короткое время ожидания для запросов на подключение. Время ожидания задается одинаково для MessageWebSocket и StreamWebSocket.

Технология веб-сокетов вызвала большое возбуждение в среде веб-разработчиков, но она еще находится в процессе развития, хотя уже имеет неплохую браузерную совместимость:

Поддержка браузерами веб-сокетов
Браузер IE Firefox Chrome Safari Opera Safari iOS Android
Минимальная версия 10 6 14 6 12.1 6 -

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

Получение доступа к веб-сокетам

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

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

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

Многие хостинговые компании не допускают долго работающих программ, если только вы не оплатите выделенный веб-сервер, т.е. сервер, обслуживающий лишь ваш сайт. Если у вас обычный общий хостинг, вы, скорее всего, не сможете размещать на нем страницы, в которых используются веб-сокеты. Даже если вы умудритесь запустить сервер веб-сокетов и удерживать его в рабочем состоянии, владелец вашего хостинга, скорее всего, выявит и выключит его.

Чтобы дать вам представление о масштабе сервера веб-сокетов, рассмотрите некоторые из задач, которые сервер сокетов должен выполнять:

содержать список всех текущих подключенных клиентов;

обрабатывать все данные в оперативной памяти, т.е. данные, доступ к которым может потребоваться всем клиентам, и делать это надежно и безопасно. Здесь имеется обилие возможных неявных проблем, например, когда один клиент пытается присоединиться к обмену, в то время как другой отключается, а информация об обоих хранится в одном и том же объекте в памяти.

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

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

Простой клиент веб-сокетов

С точки зрения веб-страницы функциональность веб-сокетов легко понять и использовать. Первый шаг — это создать объект WebSocket и передать ему URL. Код для этого подобен следующему:

Строка URL начинается с текста ws://, который идентифицирует подключение типа веб-сокет. Этот URL указывает файл веб-приложения на сервере (в данном случае это сценарий socketServer.php).

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

Если веб-страница решит, что вся ее работа выполнена, она может закрыть подключение, используя метод disconnect():

Примеры веб-сокетов в сети

Если вы заинтересованы опробовать веб-сокеты, в сети есть много сайтов, на которых можно запустить свою разработку.

Сервер веб-сокетов

Хотя этот сервер веб-сокетов и не представляет ничего особенного, на нем вы можете испробовать все возможности объекта WebSocket. Более того, к этому серверу можно подключиться со страницы, расположенной как на промышленном веб-сервере, так и на тестовом веб-сервере на вашем компьютере, или даже со страницы, просто запускаемой с жесткого диска:

Существуют и серверы веб-сокетов, предоставляющие другие возможности, включая следующие:

Многопользовательский альбом. Эта страница объединяет веб-сокеты с HTML5 Canvas. То, что вы рисуете на своем холсте, отображается на холсте других участников, и наоборот. Простой концепт, но очень впечатляющий на практике.

Серверы веб-сокетов

Чтобы иметь возможность испытать свой проект по веб-сокетам, вам нужен сервер веб-сокетов, с которым ваша страница могла бы общаться. Тестовый сервер можно найти во многих местах. Ниже даются ссылки на серверы веб-сокетов для определенных серверных языков:

Этот простой и слегка сыроватый проект будет хорошей отправной точкой для создания сервера веб-сокетов на PHP.

Существует несколько образцов сервера веб-сокетов на Ruby, но этот, применяющий модель "Event—Machine", пользуется особенной популярностью.

Сервер веб-сокетов в виде модуля расширения для Apache на языке Python.

В зависимости от того, кого вы спросите, система node.JS для разработки веб-приложений на JavaScript — это либо одна из наиболее перспективных платформ, либо просто разросшийся тестовый инструмент.

В отличие от других пунктов этого списка, Kaazing не предоставляет кода для сервера веб-сокетов. Это развитый сервер веб-сокетов, который можно лицензировать для своего веб-сайта. Для разработчиков, которые предпочитают делать все своими руками, он не будет представлять интереса. Но удобно использовать его на менее амбициозных веб-сайтах, особенно принимая во внимание то обстоятельство, что он содержит встроенную поддержку резервных решений в своих клиентских библиотеках (которые сначала пытаются применить стандарт веб-сокетов HTML5, затем Flash, а потом опрос посредством сценариев на JavaScript).

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

Замечание: У нас есть работающий пример чата, части кода из которого используются в статье. Пример будет доступен, когда инфраструктура сайта сможет должным образом поддерживать хостинг примеров с использованием веб-сокетов.

Доступность веб-сокетов

API веб-сокетов доступно в Javascript коде, область видимости которого включает объект DOM Window или любой объект, реализующий WorkerUtils ; это означает, что вы можете использовать Web Workers.

Замечание: API веб-сокетов (как и протокол лежащий в его основе) всё ещё проходят этап активной разработки; в настоящее время существует много проблем совместимости с разными браузерами (и даже с разными релизами одного и того же браузера).

Создание объекта WebSocket

Чтобы общаться через протокол веб-сокетов необходимо создать объект WebSocket ; при его создании автоматически происходит попытка открыть соединение с сервером.

Конструктор WebSocket принимает один обязательный и один необязательный параметр:

url URL, с которым происходит соединение; это должен быть URL веб-сокет-сервера. protocols Необязательный Может быть одной строкой протокола или массивом таких строк. Эти строки используют для индикации под-протоколов; таким образом, один сервер может реализовывать несколько под-протоколов веб-сокетов (к примеру, вам может потребоваться, чтобы сервер мог обрабатывать разные типы взаимодействий в зависимости от определённого под-протокола). Если вы не укажете строку протокола, то будет передана пустая строка.

В конструкторе могут возникать следующие исключения:

SECURITY_ERR Порт, к которому проводится подключение, заблокирован.

Ошибки подключения

Если ошибка случается во время попытки подключения, то в объект WebSocket сначала посылается простое событие с именем «error» (таким образом, задействуя обработчик onerror ), потом - событие CloseEvent (таким образом, задействуя обработчик onclose ) чтобы обозначить причину закрытия соединения.

Примеры

Этот простой пример создаёт новый WebSocket, подключаемый к серверу ws://www.example.com/socketserver . В данном примере в конструктор сокета в качестве дополнительного параметра передаётся пользовательский протокол "protocolOne", хотя эта часть может быть опущена.

После выполнения функции, exampleSocket . readyState будет иметь значение CONNECTING . readyState изменится на OPEN как только соединение станет готовым к передаче данных.

Если нужно открыть соединение, поддерживающее несколько протоколов, можно передать массив протоколов:

Когда соединение установлено (что соответствует, readyState OPEN ), exampleSocket.protocol сообщит, какой протокол выбрал сервер.

Отправка данных на сервер

Вы можете пересылать данные в виде строки, Blob , так и ArrayBuffer .

Замечание: До версии 11, Firefox поддерживал отправку данных только в виде строки.

Использование JSON для передачи объектов

Одна удобная вещь которую вы можете сделать, это использовать JSON для пересылки сложных данных на сервер. Например, приложение-чат может взаимодействовать с сервером, используя протокол, реализованный с использованием пакетов данных, инкапсулированных в JSON:

Получение и интерпретация JSON объектов

Давайте рассмотрим клиентское приложение чата, которое впервые упоминалось в разделе Использование JSON для передачи объектов. Есть разные типы пакетов данных, которые может получить клиент, например:

Здесь мы используем JSON.parse() чтобы преобразовать JSON строку в объект, затем обработайте его.

Формат текстовых данных

Текст, полученный через WebSocket должен иметь кодировку UTF-8

До Gecko 9.0 (Firefox 9.0 / Thunderbird 9.0 / SeaMonkey 2.6), некоторые не символьные значения в допустимом тексте UTF-8 могут привести к разрыву соединения. Теперь Gecko допускает эти значения.

Закрытие соединения

Когда вы закончили использовать соединение WebSocket, закройте его используя метод close() :

Перед попыткой закрыть соединение может быть полезно проверить атрибут bufferedAmount чтобы определить, не переданы ли еще какие-либо данные по сети.

Безопасность

Читайте также: