Что такое сокет php
Перейти к содержимому

Что такое сокет php

  • автор:

Что такое сокет в PHP

Что такое сокет в PHP

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

Сокет — это интерфейс взаимодействия клиента и сервера. Интерфейс — это, в свою очередь, правило, по которым происходит общение между клиентом и сервером. Чтобы стало понятнее, приведу пример из обычной жизни. Например, люди общаются с помощью слов на конкретном языке. Это наш с Вами интерфейс. В зависимости от входящих слов мы формируем образ у себя в голове, и отдаём ответ, в виде опять же слов. Другой пример, дельфины общаются в ультразвуком спектре, и это их интерфейс.

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

Кратко резюмирую, что же такое сокет: есть клиент, есть сервер, есть правила взаимодействия (интерфейс), клиент, согласно этим правилам, посылает запрос, а сервер данный запрос принимает и, согласно тем же правилам, даёт ответ.

Как видите, всё совсем не сложно. Очень здорово то, что клиент и сервер могут быть написаны на совсем разных языках программирования и могут находиться друг от друга за тысячи километров. Мы же с Вами будет писать и клиент, и сервер в будущих статьях на языке PHP.

Создано 13.01.2012 14:01:12

  • Михаил Русаков
  • Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!

    Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
    Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.

    Если Вы не хотите пропустить новые материалы на сайте,
    то Вы можете подписаться на обновления: Подписаться на обновления

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

    Порекомендуйте эту статью друзьям:

    Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

    1. Кнопка:
      Она выглядит вот так:
    2. Текстовая ссылка:
      Она выглядит вот так: Как создать свой сайт
    3. BB-код ссылки для форумов (например, можете поставить её в подписи):

    Комментарии ( 2 ):

    ankalitkin 14.01.2012 09:57:37

    А способ взаимодействия клиента и сервера может называться протоколом? Например ftp.

    Программирование сокетов на PHP

    Работа посвещена программированию сокетов на PHP. Для сетевого взаимодействия в PHP существует две категории функций:

    1. Функция fsockopen(string hostname, integer port, integer error_number, string error_description, double timeout) — она открывает сетевое соединение как файловый поток и возвращает дискриптор файла с которым работают функции fputs, fgets и т.д.
    2. Функции которые передают информацию непосредственно на уровне IP-протокола. И это гораздо более низкий уровень по сравнению с уровнем на котором работает функция fsockopen.

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

    Проверить это можно следующим скриптом:

    if(extension_loaded('sockets')) echo "WebSockets OK"; else echo "WebSockets UNAVAILABLE";

    Если расширение не подключено, то Вам следует его подключить.

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

    У нас будет 2 скрипта:

    1. Сервер или демон (daemon).
    2. Клиент.

    Скрипт «Клиент».

    Для реализации клиента нам понадобятся следующие функции работающие с сокетами:

    1. socket_create(integer family, integer socket_type, integer protocol); — функция создаёт сокет и возвращает ресурс сокета. Первым аргументом является семейство протокола, Если соединение будет через Internet, то задаваемое значение должно быть — AF_INET; Если соединение будет происходить через сокеты UNIX — AF_UNIX; Вторым аргументом является тип сокета. Обычно используются SOCK_STREAM для TCP взаимодействия и SOCK_DGRAM для UPD взаимодействия. Третий аргумент задаёт протокол SOL_TCP или SOL_UPD в зависимости от типа.
    2. socket_connect(resource socket, string address, integer port); — после создания сокета необходимо к нему подключится. Первым аргументом является ресурс созданного сокета, вторым IP адрес сокета если семейство протокола AF_INET, или pathname сокета Unix-домена если сокет из семейства AF_UNIX. Третьем агрументом является номер порта с которым должно быть установлено соединение.
    3. socket_read(resource socket, integer length, integer type); — функция считывает заданное в аргументе lenght количество байт из указанного сокета. По умолчанию чтение производится без учета управляющих символов, или можно задать в аргументе type — PHP_BINARY_READ, для учета управляющих символов необходимо задать значение PHP_NORMAL_READ.
    4. socket_write(resource socket, string buffer, integer length); — функция записывает данные в сокет.
    5. socket_close(resource socket); — закрывает сокет и освобождает память.

    Листинг 1.0 — Клиент

    <?php header('Content-Type: text/html; charset=utf-8'); $address = '127.0.0.1'; // адрес localhost. $port = 5555; // порт с которым будет установлено соединение. echo "Создание сокета. "; $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if ($socket < 0) < echo "Ошибка: ".socket_strerror(socket_last_error()).""; >else < echo "OK"; >echo "Подключение к сокету. "; $connect = socket_connect($socket, $address, $port); if($connect === false) < echo "Ошибка : ".socket_strerror(socket_last_error()).""; >else < echo "OK"; echo 'Сервер сказал: '; $awr = socket_read($socket, 1024); echo $awr.""; $msg = "Hello Сервер!"; echo "Говорим серверу \"".$msg."\". "; socket_write($socket, $msg, strlen($msg)); echo "OK"; echo "Сервер сказал: "; $awr = socket_read($socket, 1024); echo $awr.""; $msg = "exit"; echo "Говорим серверу \"".$msg."\". "; socket_write($socket, $msg, strlen($msg)); echo "OK"; >if(isset($socket)) ?> 

    Скрипт «Сервер».

    Для реализации сервера нам понадобятся следующие функции работающие с сокетами:

    1. Все те функции которые были описаны выше.
    2. socket_bind(resource socket, string address, integer port); — функция привязывает адрес к сокету. Аргумент addres — IP адрес сокета если семейство протокола AF_INET, или pathname сокета Unix-домена если сокет из семейства AF_UNIX.
    3. socket_listen(resource socket, integer backlog) — функция прослушивает входящие соединения в сокет. Необязательный второй аргумент устанавливает максимальный размер очереди запросов, ожидающих соединения.
    4. socket_accept(resource socket); — После того как сокет создан, привязан, и начал прослушивание, именно эта функция делает сервер сервером. Функция принимает входящие соединения.

    Листинг 1.1 — Сервер


    <?php header('Content-Type: text/html; charset=utf-8'); $address = '127.0.0.1'; $port = 5555; echo "Создание сокета . "; $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if($socket < 0) else echo "Привязывание сокета. "; $bind = socket_bind($socket, $address, $port); if($bind < 0) else echo "Прослушивание сокета. "; $listen = socket_listen($socket, 5); if($listen < 0) else while(true) else $msg = "Hello, Клиент!"; echo "Отправить клиенту \"".$msg."\". "; socket_write($accept, $msg, strlen($msg)); echo "OK"; while(true) else if ($awr == 'exit') echo "Сказать клиенту \"".$msg."\". "; socket_write($accept, $awr, strlen($awr)); echo "OK";> > if (isset($socket)) ?>

    Вначале запустите скрипт сервер, он создаст, привяжет, начнёт прослушивание сокета и установится в режим ожидания клиента. Далее запустите клиента.

    Введение

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

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

    Незнакомые с программированием сокетов могут найти много полезной информации в соответствующих man-страницах Unix, также в Интернете есть много обучающей информации по программированию сокетов на C, большая часть из которой может быть применена с небольшими изменениями к программированию сокетов на PHP. Хорошим началом может быть » FAQ по Unix-сокетам.

    User Contributed Notes

    There are no user contributed notes for this page.

    • Copyright © 2001-2023 The PHP Group
    • My PHP.net
    • Contact
    • Other PHP.net sites
    • Privacy policy

    Работа с Веб-сокетами на PHP

    PHP — едва ли первое, что придет в голову, когда стоит задача поднять сервер веб-сокетов. Практически каждая статья в интернете будет пестрить предложениями использовать для этого NodeJS, Python или Go. Но поскольку PHP — это однозначно первое, что приходит в голову, когда речь идет о веб-приложениях, почему бы не попробовать?

    На самом деле, запуск сервера веб-сокетов на PHP довольно прост. Существует превосходная библиотека Ratchet, позволяющая работать на любом фреймворке (или вовсе без него) полноценно и легко.

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

    Авторизация

    По умолчанию, сервер веб-сокетов открыт для любого подключения. Конечно, можно поставить сетевые ограничения по доменам или IP адресам, но для веб-приложения — это, мягко говоря, не эффективный подход. В обычной ситуации мы используем для таких ограничений тот или иной вариант сервиса авторизации — токены, сессии и т.д. Здесь же проблема в том, что мы не сможем отправить через протокол ws:// ни HTTP заголовок, ни cookies. Значительная часть привычных методов, таким образом, не сработает.

    Архитектура

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

    База данных

    Поскольку сервер веб-сокетов — это отдельное от основного бэкенда приложение, он ничего не знает о существующей базе данных. Сложно представить себе современное приложение на PHP, написанное без использование какого-либо фреймворка и ORM, так что перед разработчиком встанет дополнительная задача интегрировать службы, сервисы и библиотеки для работы с БД в сторонний скрипт.

    Решения

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

    Авторизуем пользователей

    В процессе подключения к серверу веб-сокетов существует этап, на котором исходный HTTP запрос преобразуется в WS запрос. Используемая нами библиотека Ratchet сохраняет этот начальный запрос в объекте Connection. Хотя возможности подцепить Bearer заголовок к запросу нет (для клиентского приложения запрос строится сразу как ws://websocket-server), мы можем передать токен (например, JWT) в параметрах запроса. При использовании HTTPS — это вполне безопасный способ передачи.

    В итоге, запрос на подключение может выглядеть примерно так:

    Строку параметров затем можно извлечь из упомянутого ранее объекта Connection.

    После извлечения токен может использоваться в любом уже применяющемся механизме авторизации, реализованном в основном приложении.

    Интегрируем базу данных

    В 9 из 10 случаев основное приложение будет написано на одном из популярных фреймворков вроде Laravel или Symfony. Все, что нам необходимо реализовать в такой ситуации — внедрение службы, отвечающей за ORM, в конструктор сервера веб-сокетов. При условии, что для запуска сервера используется консольная команда, использующая компонент Symfony Console, мы можем сделать это в два этапа: первоначальной инъекцией в конструктор консольной команды, а оттуда передачей в конструктор основного класса веб-сокетов.

    Разделяем приложения

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

    В целом, после внедрения ORM в обработчик веб-сокетов, мы могли бы выполнять все это с помощью обычных CRUD-операций. Но гораздо более эффективным решением было бы использовать уже готовый API. Почему? Во-первых, это позволит избежать дублирования кода (ровно такие же CRUDы используются в контроллерах, отвечающих за API). Во-вторых, таким способом мы укладываемся в общую архитектуру разделенных компонентов, даже внутри монолитного решения. Более того, имея одновременно токен из исходного запроса и внедренный ORM, мы получаем возможность авторизовывать действия и валидировать данные при абсолютно каждом событии веб-сокетов, а это уже полноценная имперсонификация пользователя.

    Выводы

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

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

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