Простой websocket-чат на dart

Обработка разрывов соединения

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

Реализация образца сервера

Если клиент такой простой, возможно, сложной окажется реализация сервера? Обработчик сервера для SSE может выглядеть следующим образом:

function handler(response)
{
// настраиваем заголовки для ответа с целью получить постоянное HTTP-соединение
response.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});

// составляем сообщение
response.write('id: UniqueIDn');
response.write("data: " + data + 'nn'); // каждый раз, когда мы вводим два символа новой строки, сообщение отправляется автоматически
}

Определяем функцию, которая будет обрабатывать ответ:

  1. Устанавливать заголовки;
  2. Создавать сообщение;
  3. Отправлять.

Обратите внимание, что здесь нет вызов метода send() или метода push(). Стандарт определяет: сообщение будет отправлено, как только в него будет добавлено два символа n n, как например: response.write(«data: » + data + ‘nn’);

В результате сообщение будет немедленно отправлено клиенту.

Составление сообщений

Сообщение может содержать несколько свойств:

1. ID

Если значение этого поля не содержит U + 0000 NULL, устанавливаем для буфера последнего идентификатора события значение поля. Иначе игнорируем поле.

2. Data

Добавляем значение поля в буфер, затем добавляем в буфер один символ U + 000A LINE FEED (LF).

3. Event

Устанавливаем для буфера тип события и значение поля. Это приводит к тому, что для event.type задается пользовательское имя события.

4. Retry

Если значение поля состоит только из цифр ASCII, тогда интерпретируем значение поля как целое число в десятичной системе исчисления. А также устанавливаем для времени повторного соединения потока событий это целое число. В противном случае игнорируем поле.

Все остальное будет проигнорировано. Мы не можем вводить собственные поля.

Пример с добавленным event:

response.write('id: UniqueIDn');    response.write('event: addn');    response.write('retry: 10000n');    response.write("data: " + data + 'nn');

В клиенте это обрабатывается с помощью addEventListener следующим образом:

source.addEventListener("add", function(event) {        // выполняем действия с данными        event.data;    });

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

...    id: 54    event: add    data: ""     id: 55    event: remove    data: JSON.stringify(some_data)     id: 56    event: remove    data: {    data: "msg" : "JSON data"n    data: "field": "value"n    data: "field2": "value2"n    data: }nn

Это значительно упрощает то, что мы можем сделать с нашими данными.

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

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

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

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

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

Метод первый, напрямую использовать Workerman для открытия SSL

Готов к работе:

1. Версия Workerman не ниже 3.3.7

2. PHP устанавливает расширение openssl

3. Сертификат (файл pem / crt и файл ключа) был подан и помещен в любой каталог на диске.

Код:

С помощью приведенного выше кода Workerman отслеживает протокол wss, а клиент может подключаться к workerman через протокол wss для реализации безопасного обмена мгновенными сообщениями.

тест

Откройте браузер Chrome, нажмите F12, чтобы открыть консоль отладки, введите в столбце Console (или поместите следующий код на страницу html для запуска с js)

нота:

1. Если не запускается, порт 443 обычно занят. Переключитесь на другой порт

Обратите внимание, что после перехода на другой порт клиенту необходимо указать номер порта при подключении. Адрес при подключении клиента похож на wss: //domain.com: xxx, xxx — номер порта

Если вы должны использовать порт 443, используйте второй метод для реализации wss в качестве прокси.

2. К порту wss можно получить доступ только через протокол wss, а ws не может получить доступ к порту wss.

3. Сертификат обычно привязан к имени домена, поэтому при тестировании клиента используйте для подключения имя домена вместо ip.

4. Если вы не можете получить доступ, проверьте брандмауэр сервера.

5. Для этого метода требуется версия PHP> = 5.6, поскольку апплет WeChat требует tls1.2, а версии ниже PHP5.6 не поддерживают tls1.2.

Метод второй: используйте nginx / apache для прокси-сервера wss

В дополнение к использованию собственного SSL Workerman вы также можете использовать nginx / apache в качестве прокси-сервера wss для перенаправления на workerman (обратите внимание, что часть workerman этого метода не должна устанавливать ssl, иначе он не сможет подключиться). Принцип и процесс коммуникации:

Принцип и процесс коммуникации:

1. Клиент инициирует соединение wss для подключения к nginx / apache.

2. nginx / apache преобразует данные протокола wss в данные протокола ws и пересылает их на порт протокола WebSocket Workerman.

3. Workerman выполняет обработку бизнес-логики после получения данных.

4. Когда Workerman отправляет сообщение клиенту, происходит обратный процесс. Данные преобразуются в протокол wss с помощью nginx / apache и затем отправляются клиенту.

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

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

socket.close();

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

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

// Показываем сообщение «disconnected», когда соединение разорвано.
socket.onclose = function(event) {
socketStatus.innerHTML = 'Disconnectedfrom WebSocket.';
socketStatus.className = 'closed';
};

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

// Закрываем соединение при нажатии кнопки «close»
closeBtn.onclick = function(e) {
e.preventDefault();

  // Закрываем веб-сокет.
  socket.close();

  return false;
};

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

Откройте файл index.html в браузере и попробуйте отправить несколько сообщений. Вы увидите, что сервер отправляет сообщения обратно.

Example¶

Here’s a WebSocket server example. It reads a name from the client and sends a
message.

#!/usr/bin/env python

import asyncio
import websockets

@asyncio.coroutine
def hello(websocket, path):
    name = yield from websocket.recv()
    print("< {}".format(name))
    greeting = "Hello {}!".format(name)
    yield from websocket.send(greeting)
    print("> {}".format(greeting))

start_server = websockets.serve(hello, 'localhost', 8765)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

Here’s a corresponding client example.

#!/usr/bin/env python

import asyncio
import websockets

@asyncio.coroutine
def hello():
    websocket = yield from websockets.connect('ws://localhost:8765/')
    name = input("What's your name? ")
    yield from websocket.send(name)
    print("> {}".format(name))
    greeting = yield from websocket.recv()
    print("< {}".format(greeting))

asyncio.get_event_loop().run_until_complete(hello())

Передача данных

Поток данных в WebSocket состоит из «фреймов», фрагментов данных, которые могут быть отправлены любой стороной, и которые могут быть следующих видов:

  • «текстовые фреймы» – содержат текстовые данные, которые стороны отправляют друг другу.
  • «бинарные фреймы» – содержат бинарные данные, которые стороны отправляют друг другу.
  • «пинг-понг фреймы» используется для проверки соединения; отправляется с сервера, браузер реагирует на них автоматически.
  • также есть «фрейм закрытия соединения» и некоторые другие служебные фреймы.

В браузере мы напрямую работаем только с текстовыми и бинарными фреймами.

Метод WebSocket может отправлять и текстовые и бинарные данные.

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

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

Это задаётся свойством , по умолчанию оно равно , так что бинарные данные поступают в виде -объектов.

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

Cheat sheet¶

Server

  • Write a coroutine that handles a single connection. It receives a websocket
    protocol instance and the URI path in argument.

    • Call and
      to receive and
      send messages at any time.
    • You may or
      if you wish
      but it isn’t needed in general.
  • Create a server with which is similar to
    asyncio’s .

    • The server takes care of establishing connections, then lets the handler
      execute the application logic, and finally closes the connection after
      the handler returns.
    • You may subclass and
      pass it in the keyword argument for advanced customization.

Client

  • Create a server with which is similar to
    asyncio’s .
  • Call and
    to receive and
    send messages at any time.
  • You may or
    if you wish but it
    isn’t needed in general.
  • Call to terminate
    the connection.

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

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

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

Стандарт веб-сокетов также поддерживает URL, которые начинаются с текста wss://, что указывает на требование использовать безопасное, зашифрованное подключение (точно так же, как и при запросе веб-страницы указывается URL, начинающийся с https:// вместо http://).

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

Само обстоятельство создания объекта WebSocket понуждает страницу пытаться подключиться к серверу. Дальше надо использовать одно из четырех событий объекта WebSocket: onOpen (при установлении подключения), onError (когда возникает ошибка), onClose (при закрытии подключения) и onMessage (когда страница получает сообщение от сервера):

Например, в случае успешного подключения неплохо бы отправить соответствующее подтверждающее сообщение. Такое сообщение доставляется с помощью метода send() объекта WebSocket, которому в качестве параметра передается обычный текст. Далее приведена функция, которая обрабатывает событие onopen и отправляет сообщение:

Предположительно, веб-сервер получит это сообщение и даст на него ответ.

События onError и onClose можно использовать для отправки извещений посетителю веб-страницы. Но безоговорочно самым важным является событие onMessage, которое срабатывает при получении новых данных от сервера. Опять же, код JavaScript для обработки этого события не представляет никаких сложностей — мы просто извлекаем текст сообщения из свойства data:

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

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

Чтобы заставить подключение веб-сокетов работать, выполняется большой объем работы за кулисами. Прежде всего, веб-страница устанавливает связь по обычному стандарту HTTP. Потом это подключение нужно повысить до подключения веб-сокетов, позволяющего свободную двустороннюю связь. На этом этапе возможны проблемы, если между компьютером клиента и веб-сервером находится прокси-сервер (как, например, в типичной корпоративной сети). Прокси-сервер может отказаться сотрудничать и разорвет подключение. Эту проблему можно решить, обнаруживая неудачное подключение (посредством события onError объекта WebSocket) и применяя один из заполнителей (polyfills) для сокетов, описанных на веб-сайте GitHub. Эти заполнители применяют метод опроса, чтобы эмулировать подключение веб-сокетов.

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

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

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

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

Протокол работы с фреймами

  • (1 бит): указывает на то, является ли этот фрейм последним фреймом, завершающим передачу сообщения. Чаще всего для передачи сообщения достаточно одного фрейма и этот бит всегда оказывается установленным. Эксперименты показали, что Firefox создаёт второй фрейм после того, как размер сообщения превысит 32 Кб.
  • , , (каждое по 1-му биту): эти поля должны быть установлены в 0, только если не было достигнуто договорённости о расширениях, которая и определит смысл их ненулевых значений. Если в одном из этих полей будет установлено ненулевое значение и при этом не было достигнуто договорённости о смысле этого значения, получатель должен признать соединение недействительным.
  • (4 бита): здесь закодированы сведения о содержимом фрейма. В настоящее время используются следующие значения:

    • : в этом фрейме находится следующая часть передаваемого сообщения.
    • : в этом фрейме находятся текстовые данные.
    • : в этом фрейме находятся бинарные данные.
    • : этот фрейм завершает соединение.
    • : это ping-фрейм.
    • : это pong-фрейм.
  • (1 бит): указывает на то, что фрейм замаскирован. Сейчас дело обстоит так, что каждое сообщение от клиента к серверу должно быть замаскировано, в противном случае спецификации предписывают разрывать соединения.
  • (7 битов): длина полезной нагрузки. Фреймы WebSocket поддерживают следующие методы указания размеров полезной нагрузки. Значение 0-125 указывает на длину полезной нагрузки. 126 означает, что следующие два байта означают размер. 127 означает, что следующие 8 байтов содержат сведения о размере. В результате длина полезной нагрузки может быть записана примерно в 7 битах, или в 16, или в 64-х.
  • (32 бита): все фреймы, отправленные с клиента на сервер, замаскированы с помощью 32-битного значения, которое содержится во фрейме.
  • : передаваемые во фрейме данные, которые, наверняка, замаскированы. Их длина соответствует тому, что задано в .

вот интересное обсуждение

Реализация сервера на PHP

Исходники простого WebSocket echo-сервера выложил сюда.
Код хорошо документирован, но я всё же опишу некоторые тонкости реализации.
Чтобы «поднять» WebSocket сервер нужно создать обычный TCP-сервер.
В PHP TCP-сервер реализуется через «stream_socket» или через PHP расширение «sockets».
Различия между ними в том, что «stream_socket» работает на встроенных функциях PHP для работы с потоками, «sockets» же работает через модуль PHP и повторяет функции для работы с сокетами в языке «C».
Я выбрал «sockets».

Процесс реализован через «while» с задержкой 0.2 секунды.
Процесс не форкается и сообщения выбрасывает в консоль, поэтому запускать необходимо только через консоль.
Для того, чтобы обслуживать несколько клиентов одновременно, сокет делаю неблокирующим и через «socket_select»
каждые 0.2 секунды прослушиваю сокет.
При рукопожатии проверяю только наличие заголовков.

Фреймы парсю через «pack/unpack».
Сервер не понимает фрагментированных фреймов.
Сервер выдаёт только незамаскированные сообщения, т.к. некоторые браузеры не понимают замаскированных сообщений.
Сервер реагирует только на текстовые фреймы и фрейм закрытия соединения, бинарные фреймы не понимает.

Ну собственно всё, удачи в исследовании этого не простого протокола.

Или getting started with WebSocket PHP без phpDaemon

Здравствуйте! Простите за столь длинный заголовок, но, надеюсь, что новичкам вроде меня будет легче найти эту статью, ведь мне ничего подобного найти не удалось. Несколько недель назад я принял решение переработать игровой клиент и сервер своей игры Growing Crystals с AJAX, на WebSocket, но всё оказалось не просто непросто, а очень сложно. Поэтому я и решил написать статью, которая бы помогла самым что ни на есть начинающим разработчикам на WebSocket + PHP сэкономить несколько дней времени, максимально подробно объясняя каждый свой шаг по настройке и запуску первого WebSocket скрипта на PHP.

Что у меня есть: Денвер на локальной машине, на нём я веду разработку проекта и дешевый PHP хостинг, на котором я публикую свой проект для того, чтобы получить обратную связь от Интернет-пользователей.

Что я хочу: Без установки phpDaemon (phpd), NodeJS и прочих вещей на локальную машину и хостинг, продолжить разработку своего проекта, но теперь с WebSocket, в этой статье разберем простой WebSocket эхо сервер.

Чего я не хочу: Говоря о NodeJS, не хочется переписывать серерную логику с PHP на другой язык, тем более устанавливать NodeJS, хотя и люблю JavaScript больше чем PHP.

Важно: не путайте демона написанного на php, с фреймворком асинхронных приложений phpDaemon. Который, конечно же, обязательно потребуется в случае развития проекта и многократного роста нагрузки на хостинг

Но для начала работы с WebSocket на дешевом хостинге можно обойтись и без него.

Data transfer

WebSocket communication consists of “frames” – data fragments, that can be sent from either side, and can be of several kinds:

  • “text frames” – contain text data that parties send to each other.
  • “binary data frames” – contain binary data that parties send to each other.
  • “ping/pong frames” are used to check the connection, sent from the server, the browser responds to these automatically.
  • there’s also “connection close frame” and a few other service frames.

In the browser, we directly work only with text or binary frames.

WebSocket method can send either text or binary data.

A call allows in string or a binary format, including , , etc. No settings required: just send it out in any format.

When we receive the data, text always comes as string. And for binary data, we can choose between and formats.

That’s set by property, it’s by default, so binary data comes as objects.

Blob is a high-level binary object, it directly integrates with , and other tags, so that’s a sane default. But for binary processing, to access individual data bytes, we can change it to :

Node.js Socket Example

Let’s say you need to write a server application, and you chose Node.js as your programming language. Your users can be any type of client, like a web browser, mobile app, IoT device, Node.js client, or anything that knows TCP.

You need to serve assets to your users over HTTP, but you also need to provide them with streams for bi-directional messaging. We can accomplish this in a single Node.js server app!

The code from the video, and also this article is available in my Node.js WebSocket Examples GitHub Repository.

First we’ll go over some plain socket code, followed by WebSocket code. If you already serve assets with something like Express.js, Hapi, or the native Node.js HTTP library, we can jump into the socket code.

Socket Server JavaScript Code

// Node.js socket server script
const net = require('net');

// Create a server object
const server = net.createServer((socket) => {
  socket.on('data', (data) => {
    console.log(data.toString());
  });

  socket.write('SERVER: Hello! This is server speaking.');
  socket.end('SERVER: Closing connection now.');
}).on('error', (err) => {
  console.error(err);
});

// Open server on port 9898
server.listen(9898, () => {
  console.log('opened server on', server.address().port);
});

This script runs a Node.js socket server on port 9898. Whenever a client connects to this server app (IP_ADDRESS:9898) the server sends the client a string over the open socket. It says “SERVER: Hello! This is server speaking.” Whenever the client sends some data to the server, the Node.js script logs the contents in the ‘data’ event handler.

Socket Client JavaScript Code

Here we have our Node.js socket client script, which can connect to the Node.js socket server above.

// Node.js socket client script
const net = require('net');

// Connect to a server @ port 9898
const client = net.createConnection({ port: 9898 }, () => {
  console.log('CLIENT: I connected to the server.');
  client.write('CLIENT: Hello this is client!');
});

client.on('data', (data) => {
  console.log(data.toString());
  client.end();
});

client.on('end', () => {
  console.log('CLIENT: I disconnected from the server.');
});

The client script attempts to connect to localhost:9898. If the connection succeeds, then the client sends a string to the server over the open socket. It says “CLIENT: Hello this is client!” Whenever the server sends some data to the client, the client logs it in the ‘data’ event handler.

This is what the output looks like for client and server Node.js socket scripts running on the command line.

Connection close

Normally, when a party wants to close the connection (both browser and server have equal rights), they send a “connection close frame” with a numeric code and a textual reason.

The method for that is:

  • is a special WebSocket closing code (optional)
  • is a string that describes the reason of closing (optional)

Then the other party in event handler gets the code and the reason, e.g.:

Most common code values:

  • – the default, normal closure (used if no supplied),
  • – no way to set such code manually, indicates that the connection was lost (no close frame).

There are other codes like:

  • – the party is going away, e.g. server is shutting down, or a browser leaves the page,
  • – the message is too big to process,
  • – unexpected error on server,
  • …and so on.

The full list can be found in .

WebSocket codes are somewhat like HTTP codes, but different. In particular, any codes less than are reserved, there’ll be an error if we try to set such a code.

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

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

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

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

Low-level API¶

Exceptions

exception

Exception raised when a handshake request or response is invalid.

exception

Exception raised when an operation is forbidden in the current state.

exception

Exception raised when an URI is invalid.

Opening handshake

The module deals with the WebSocket opening
handshake according to .

It provides functions to implement the handshake with any existing HTTP
library. You must pass to these functions:

  • A set_header function accepting a header name and a header value,
  • A get_header function accepting a header name and returning the header
    value.

The inputs and outputs of get_header and set_header are
objects containing only ASCII characters.

Some checks cannot be performed because they depend too much on the
context; instead, they’re documented below.

To accept a connection, a server must:

  • Read the request, check that the method is GET, and check the headers with
    ,
  • Send a 101 response to the client with the headers created by
    if the request is valid; otherwise, send a 400.

To open a connection, a client must:

  • Send a GET request to the server with the headers created by
    ,
  • Read the response, check that the status code is 101, and check the headers
    with .
(set_header)

Build a handshake request to send to the server.

Return the key which must be passed to .

(get_header)

Check a handshake request received from the client.

If the handshake is valid, this function returns the key which must be
passed to .

Otherwise, it raises an exception and the server
must return an error, usually 400 Bad Request.

This function doesn’t verify that the request is an HTTP/1.1 or higher GET
request and doesn’t perform Host and Origin checks. These controls are
usually performed earlier in the HTTP request handling code. They’re the
responsibility of the caller.

(set_header, key)

Build a handshake response to send to the client.

key comes from .

(get_header, key)

Check a handshake response received from the server.

key comes from .

If the handshake is valid, this function returns .

Otherwise, it raises an exception.

This function doesn’t verify that the response is an HTTP/1.1 or higher
response with a 101 status code. These controls are the responsibility of
the caller.

Data transfer

The module implements data framing as specified in
.

It deals with a single frame at a time. Anything that depends on the sequence
of frames is implemented in .

class (fin, opcode, data)

Alias for field number 2

Alias for field number 0

Alias for field number 1

(reader, mask, *, max_size=None)

Read a WebSocket frame and return a object.

reader is a coroutine taking an integer argument and reading exactly this
number of bytes, unless the end of file is reached.

mask is a telling whether the frame should be masked, ie.
whether the read happens on the server side.

If max_size is set and the payload exceeds this size in bytes,
is raised.

This function validates the frame before returning it and raises
if it contains incorrect values.

(frame, writer, mask)

Write a WebSocket frame.

frame is the object to write.

writer is a function accepting bytes.

mask is a telling whether the frame should be masked, ie.
whether the write happens on the client side.

This function validates the frame before sending it and raises
if it contains incorrect values.

(data)

Parse the data in a close frame.

Return (code, reason) when code is an and reason a
.

Raise or if the
data is invalid.

(code, reason)

Serialize the data for a close frame.

This is the reverse of .

URI parser

The module implements parsing of WebSocket URIs
according to .

(uri)

This function parses and validates a WebSocket URI.

If the URI is valid, it returns a namedtuple (secure, host, port,
resource_name)

Otherwise, it raises an exception.

Chat example

Let’s review a chat example using browser WebSocket API and Node.js WebSocket module https://github.com/websockets/ws. We’ll pay the main attention to the client side, but the server is also simple.

HTML: we need a to send messages and a for incoming messages:

From JavaScript we want three things:

  1. Open the connection.
  2. On form submission – for the message.
  3. On incoming message – append it to .

Here’s the code:

Server-side code is a little bit beyond our scope. Here we’ll use Node.js, but you don’t have to. Other platforms also have their means to work with WebSocket.

The server-side algorithm will be:

  1. Create – a set of sockets.
  2. For each accepted websocket, add it to the set and setup event listener to get its messages.
  3. When a message received: iterate over clients and send it to everyone.
  4. When a connection is closed: .

Here’s the working example:

You can also download it (upper-right button in the iframe) and run locally. Just don’t forget to install Node.js and before running.

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector