websocket js php пример

Делаем вебсокеты на PHP с нуля

Некоторое время назад я выбирал библиотеку для работы с вебсокетами. На просторах интернета я натыкался на статьи по интеграции node.js с yii, а почти все статьи о вебсокетах на хабре ограничивались инструкциями к тому, как использовать phpdaemon.

Я изучал библиотеки phpdaemon и ratchet, они достаточно монструозны (причём используя ratchet для отправки сообщения конкретному пользователю рекомендовано дополнительно использовать wamp). Мне не совсем было понятно для чего использовать таких монстров, которые требуют установку других монстров. Почитав исходники этих, а также других библиотек, я разобрался как всё устроено и мне захотелось написать простой вебсокет-сервер на php самостоятельно. Это помогло мне закрепить изученный материал и наткнуться на некоторые подводные камни, о которых я не имел представления.

Так я решил написать необходимый для меня функционал с нуля.

Получившийся код и ссылка на демонстрационный чат в конце статьи.

Поставленные цели:

1) разобраться с серверными сокетами в php
2) разобраться с протоколом вебсокетов
3) написать с нуля простой сервер вебсокетов

1) Серверные сокеты в php

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

используя расширение php «socket»:

или используя расширение php «stream»:

Я предпочёл второй вариант ввиду его краткости.

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

или с использованием stream_select

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

2) Протокол вебсокетов

«Рукопожатие» или handshake:

Считываем значение Sec-WebSocket-Key из пришедшего заголовка от клиента, рассчитываем на его основе Sec-WebSocket-Accept и отправляем итоговый ответ:

обмен сообщениями

Простой сервер вебсокетов

Итак, у нас есть вся необходимая информация.
Используя код простого http сервера из первой части, а также функции handshake, decode и encode из второй мы можем собрать простой сервер вебсокетов.

В приведённом примере можно менять пользовательские сценарии onOpen, onClose и onMessage для реализации необходимого функционала.

Поставленные цели достигнуты.
Если этот материал вам покажется интересным, то в следующей статье я опишу как можно запускать несколько процессов для обработки соединений (один мастер и несколько воркеров), межпроцессное взаимодействие, интеграцию с вашим фреймворком на примере компонента yii.

Источник

WebSocket сервер на PHP

Протокол WebSocket предназначен для решения разных задач и снятия ограничений обмена данными между браузером и сервером. Он позволяет пересылать любые данные, на любой домен, безопасно и почти без лишнего сетевого трафика. Для установления соединения WebSocket клиент и сервер используют протокол, похожий на HTTP. Клиент формирует особый HTTP-запрос, на который сервер отвечает определенным образом.

Простой сокет-сервер

В первую очередь надо в файле php.ini расскомментировать строку, позволяющую работать с сокетами и перезапустить сервер:

Вот как выглядит простейший сокет-сервер:

Запустим его в работу:

websocket js php пример. Смотреть фото websocket js php пример. Смотреть картинку websocket js php пример. Картинка про websocket js php пример. Фото websocket js php пример

Попробуем пообщаться с сервером с помощью telnet :

websocket js php пример. Смотреть фото websocket js php пример. Смотреть картинку websocket js php пример. Картинка про websocket js php пример. Фото websocket js php пример

И видим сообщение от сервера:

websocket js php пример. Смотреть фото websocket js php пример. Смотреть картинку websocket js php пример. Картинка про websocket js php пример. Фото websocket js php пример

Наш сервер в другом окне тоже встрепенулся:

websocket js php пример. Смотреть фото websocket js php пример. Смотреть картинку websocket js php пример. Картинка про websocket js php пример. Фото websocket js php пример

WebSocket сервер

Протокол WebSocket работает над TCP. Это означает, что при соединении браузер отправляет по HTTP специальные заголовки, спрашивая: «Поддерживает ли сервер WebSocket?». Если сервер в ответных заголовках отвечает «Да, поддерживаю», то дальше HTTP прекращается и общение идёт на специальном протоколе WebSocket, который уже не имеет с HTTP ничего общего.

Здесь GET и Host — стандартные HTTP-заголовки, а Upgrade и Connection указывают, что браузер хочет перейти на WebSocket.

Для тестирования работы сервера нам нужен клиент:

Проверим его в работе. Открываем HTML-страницу в браузере и заполняем первое поле «Сервер»:

Это гарантированно работающий WebSocket echo-сервер, которые отправляет все сообщения обратно. Жмем кнопку «Установить соединение», набираем текст сообщения в поле «Сообщение», жмем кнопку «Отправить сообщение»:

websocket js php пример. Смотреть фото websocket js php пример. Смотреть картинку websocket js php пример. Картинка про websocket js php пример. Фото websocket js php пример

А теперь код WebSocket сервера на PHP:

Для тестирования напишем небольшой PHP-скрипт, который запускает в работу сервер и все сообщения клиента отправляет обратно (echo-сервер):

Запускаем скрипт в работу:

websocket js php пример. Смотреть фото websocket js php пример. Смотреть картинку websocket js php пример. Картинка про websocket js php пример. Фото websocket js php пример

Еще один пример использования сервера — клиент отправляет команды, а сервер их выполняет:

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

Источник

WebSocket

Протокол WebSocket («веб-сокет»), описанный в спецификации RFC 6455, обеспечивает возможность обмена данными между браузером и сервером через постоянное соединение. Данные передаются по нему в обоих направлениях в виде «пакетов», без разрыва соединения и дополнительных HTTP-запросов.

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

Простой пример

Протокол wss:// не только использует шифрование, но и обладает повышенной надёжностью.

Это потому, что данные ws:// не зашифрованы, видны для любого посредника. Старые прокси-серверы не знают о WebSocket, они могут увидеть «странные» заголовки и закрыть соединение.

С другой стороны, wss:// – это WebSocket поверх TLS (так же, как HTTPS – это HTTP поверх TLS), безопасный транспортный уровень шифрует данные от отправителя и расшифровывает на стороне получателя. Пакеты данных передаются в зашифрованном виде через прокси, которые не могут видеть, что внутри, и всегда пропускают их.

Как только объект WebSocket создан, мы должны слушать его события. Их всего 4:

…А если мы хотим отправить что-нибудь, то вызов socket.send(data) сделает это.

Для демонстрации есть небольшой пример сервера server.js, написанного на Node.js, для запуска примера выше. Он отвечает «Привет с сервера, Джон», после ожидает 5 секунд и закрывает соединение.

В общем-то, всё, мы уже можем общаться по протоколу WebSocket. Просто, не так ли?

Теперь давайте поговорим более подробно.

Открытие веб-сокета

Когда new WebSocket(url) создан, он тут же сам начинает устанавливать соединение.

Браузер, при помощи специальных заголовков, спрашивает сервер: «Ты поддерживаешь Websocket?» и если сервер отвечает «да», они начинают работать по протоколу WebSocket, который уже не является HTTP.

Мы не можем использовать XMLHttpRequest или fetch для создания такого HTTP-запроса, потому что JavaScript не позволяет устанавливать такие заголовки.

Если сервер согласен переключиться на WebSocket, то он должен отправить в ответ код 101:

После этого данные передаются по протоколу WebSocket, и вскоре мы увидим его структуру («фреймы»). И это вовсе не HTTP.

Расширения и подпротоколы

Sec-WebSocket-Extensions: deflate-frame означает, что браузер поддерживает сжатие данных. Расширение – это что-то, связанное с передачей данных, расширяющее сам протокол WebSocket. Заголовок Sec-WebSocket-Extensions отправляется браузером автоматически со списком всевозможных расширений, которые он поддерживает.

Sec-WebSocket-Protocol: soap, wamp означает, что мы будем передавать не только произвольные данные, но и данные в протоколах SOAP или WAMP (The WebSocket Application Messaging Protocol» – «протокол обмена сообщениями WebSocket приложений»). То есть, этот заголовок описывает не передачу, а формат данных, который мы собираемся использовать. Официальные подпротоколы WebSocket регистрируются в каталоге IANA.

Сервер должен ответить перечнем протоколов и расширений, которые он может использовать.

Здесь сервер отвечает, что поддерживает расширение – deflate-frame и может использовать только протокол SOAP из всего списка запрошенных подпротоколов.

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

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

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

Ограничение скорости

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

Мы можем вызывать socket.send(data) снова и снова. Но данные будут буферизованы (сохранены) в памяти и отправлены лишь с той скоростью, которую позволяет сеть.

Свойство socket.bufferedAmount хранит количество байт буферизованных данных на текущий момент, ожидающих отправки по сети.

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

Закрытие подключения

Обычно, когда сторона хочет закрыть соединение (браузер и сервер имеют равные права), они отправляют «фрейм закрытия соединения» с кодом закрытия и указывают причину в виде текста.

code – это не любое число, а специальный код закрытия WebSocket.

Наиболее распространённые значения:

Есть и другие коды:

Полный список находится в RFC6455, §7.4.1.

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

Состояние соединения

Чтобы получить состояние соединения, существует дополнительное свойство socket.readyState со значениями:

Пример чата

Давайте рассмотрим пример чата с использованием WebSocket API и модуля WebSocket сервера Node.js https://github.com/websockets/ws. Основное внимание мы, конечно, уделим клиентской части, но и серверная весьма проста.

HTML: нам нужна форма

От JavaScript мы хотим 3 вещи:

Серверный код выходит за рамки этой главы. Здесь мы будем использовать Node.js, но вы не обязаны это делать. Другие платформы также поддерживают средства для работы с WebSocket.

Серверный алгоритм действий будет таким:

Вот рабочий пример:

Вы также можете скачать его (верхняя правая кнопка в ифрейме) и запустить локально. Только не забудьте установить Node.js и выполнить команду npm install ws до запуска.

Итого

WebSocket – это современный способ иметь постоянное соединение между браузером и сервером.

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

Иногда, чтобы добавить WebSocket к уже существующему проекту, WebSocket-сервер запускают параллельно с основным сервером. Они совместно использует одну базу данных. Запросы к WebSocket отправляются на wss://ws.site.com – поддомен, который ведёт к WebSocket-серверу, в то время как https://site.com ведёт на основной HTTP-сервер.

Конечно, возможны и другие пути интеграции.

Источник

Вебсокеты на php. Выбираем вебсокет-сервер

Давным-давно я публиковал статью на хабре, как написать свой вебсокет-сервер с нуля. Статья переросла в библиотеку. Несколько месяцев я занимался её развитием, ещё несколько лет — поддержкой и багфиксом. Написал модуль интеграции с yii2. Какой-то энтузиаст написал интеграцию с laravel. Моя библиотека совместима с php7. Недавно я решил отказаться от её дальнейшей поддержки (причины ниже), поэтому хочу помочь её пользователям перейти на другую библиотеку.

websocket js php пример. Смотреть фото websocket js php пример. Смотреть картинку websocket js php пример. Картинка про websocket js php пример. Фото websocket js php пример

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

phpdaemon

Ratchet

В итоге я написал библиотеку для себя и поделился ею с сообществом на гитхабе. Сделал несколько демок (в том числе игру «танчики»). Переписал стороннюю игру (с разрешения авторов) с node.js на свою библиотеку. Делал нагрузочное тестирование. Демки работали годами без перезагрузки. Старался отвечать на тикеты в течения дня. Всё это показывало, что моя библиотека может быть использована на продакшене и многие её использовали.

Была единственная проблема. Мне хватало моей библиотеки для использования в своих проектах, а вот другим нет. Они хотели, чтобы я её развивал, а мне это было не нужно. Кому-то требовалась поддержка windows, а кому-то ssl, pg_notify, safari, pthreads и многое другое. Открытые тикеты с запросами на реализацию различного функционала висят годами.

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

Workerman

Если загуглить «php websocket», то первая страница — это моя статья на Хабре, а вторая — «Ratchet», который кому-то может показаться сложным и он выберет из-за этого мою библиотеку или вообще откажется от идеи делать вебсокеты.

Что ж, пришло время исправить эту досадную ошибку и донести до как можно большего количества людей о существовании такой библиотеки как Workerman и привести несколько примеров по её использованию.

На главной странице проекта в гитхабе уже есть несколько примеров. Рассмотрим один из них:

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

код сервера server.php:

код клиента client.html:

код отправки сообщений с нашего сайта send.php:

Справедливости ради я решил написать такой же пример для ratchet, но документация мне не помогла, как 3 года назад. Зато на stackoverflow предложили немного костыльный, но рабочий вариант: соединяться из своего php-скрипта по ws-соединению. Конечно это не так же просто как соединиться с tcp-сокетом с помощью stream_socket_client и отправить сообщение с помощью fwrite. Но уже что-то.

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

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

Update: в комментариях рекомендуют swoole. Я натыкался на эту библиотеку ранее, но у меня сложилось ложное впечатление, что что она не поддерживает php7 и после этого она выпала из моего круга зрения. А зря. Интересная библиотека.

Источник

Как применять вебсокеты js в связке с php?

Хочу написать простенький чат на сокетах js. В js это реализовано на стандарте RFC 6455, открытие сокета производится следующей строчкой:

Еще не понятно как это всё обрабатывать на стороне сервера (php), все примеры которые я встречал были на node.js, а что с php, подскажите?

2 ответа 2

Ты можешь создать сокет соединение на php, код ниже. Далее ты попросту обрабатываешь все сообщения которые приходят. В браузере на js уже подключаешься к 127.0.0.1:8000.

websocket js php пример. Смотреть фото websocket js php пример. Смотреть картинку websocket js php пример. Картинка про websocket js php пример. Фото websocket js php пример

В первую очередь нужно понять что сокет соеденение состоит из двух частей.
1.Сокет клиент который подключает к определенному порту (скажем 8080)
2. Сокет сервер который слушает определенный порт (8080) и если ему обратился сокетКлиент то создается соединение.

В js нужно естественно писать точный адресс. Обязательно указовать порт потому что сокет сидит только в канкретном порту. т.е. адрес выглядит как то так «192.168.1.1:8080». Это пример подключения к конкретному 8080 порту. Можно указать любой порт. Желательно редкий. Если порт будет занят то сокет не заработает. что насчет Реализации на пхп. Если честно на пхп сокет не серьезно. Именна изза сокета я в свое время перешол на Ява для веб и не пожелел. Но думаю если захотеть то можно найти примеры. Если не ошибаюсь я видел какойто готовый фреймворк толи библиотеку на пхп для реализации чата с помощью сокета. RedChat кажется точно не помню. Если вы не пишите серьезный чат то можно возпользоваться но если хотите серьезное программу которая работала без отказна то переходи на что нибудь по серьезней. Я сделал выбор в сторону Java. Выбор большой от c# до python.
Ну и еще если вы новичек (а вы скорее всего новичек) То оссобенность сокета в том что простой запрос проходит по схеме запрос->ответ->соединение разрывается то сокет просто соеденяется и не разрывает соеденение пока один из них не захочит выйти. Сокет соединяется и нужно там в бесконечно цикле выводить данные. при каждой итерации js будит ловить отправленные тобой данные и делать че надо. Сокет на пхп мне лично показался геморойным когда я хотел ее изучить. Я нашел хороший пример от Михаила Русакова. Вбей в гугл там в топах найдешь. Хороший робочий пример.
Удачи в освоении программирования 😉

Источник

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

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