Сокеты php что это
Этот пример показывает работу простого сервера. Измените переменные address и port в соответствии с вашими настройками и выполните. Затем вы можете соединиться с сервером с командой, похожей на: telnet 192.168.1.53 10000 (где адрес и порт должны соответствовать вашим настройкам). Всё, что вы наберёте на клавиатуре, будет затем выведено на сервере и отправлено вам обратно. Для отключения наберите 'выход'.
/* Позволяет скрипту ожидать соединения бесконечно. */
set_time_limit ( 0 );
/* Включает скрытое очищение вывода так, что мы видим данные
* как только они появляются. */
ob_implicit_flush ();
$address = '192.168.1.53' ;
$port = 10000 ;
if (( $sock = socket_create ( AF_INET , SOCK_STREAM , SOL_TCP )) === false ) echo "Не удалось выполнить socket_create(): причина: " . socket_strerror ( socket_last_error ()) . "\n" ;
>
if ( socket_bind ( $sock , $address , $port ) === false ) echo "Не удалось выполнить socket_bind(): причина: " . socket_strerror ( socket_last_error ( $sock )) . "\n" ;
>
if ( socket_listen ( $sock , 5 ) === false ) echo "Не удалось выполнить socket_listen(): причина: " . socket_strerror ( socket_last_error ( $sock )) . "\n" ;
>
do if ( false === ( $buf = socket_read ( $msgsock , 2048 , PHP_NORMAL_READ ))) echo "Не удалось выполнить socket_read(): причина: " . socket_strerror ( socket_last_error ( $msgsock )) . "\n" ;
break 2 ;
>
if (! $buf = trim ( $buf )) continue;
>
if ( $buf == 'выход' ) break;
>
if ( $buf == 'выключение' ) socket_close ( $msgsock );
break 2 ;
>
$talkback = "PHP: Вы сказали ' $buf '.\n" ;
socket_write ( $msgsock , $talkback , strlen ( $talkback ));
echo " $buf \n" ;
> while ( true );
socket_close ( $msgsock );
> while ( true );
echo "
Комментарии ( 9 ):
Михаил,вы сами проверяли свой скрипт клиента относительно серверу? Вот нмпример строка $result = socket_connect($socket, $address, $port); как она должна подключаться если переменной $socket нет,а есть $sock. Или я ошибаюсь?=)
Для начала с примером в статье и разберитесь. Как именно реализовать это для игрового сервера, это уже другой вопрос.
Не подключается, возможно, сервер не сделали, чтобы было куда подключаться.
Вроде все сделал правильно! Если в браузере отткрыт фаил "server.php" то все срабатывает нормально, но только один раз. Что можно сделать? Я вроде все установил как надо
Михаил, Здравствуйте. Я сохранил код сервера и код клиента, затем открыл вкладку в браузере через которую запустил код сервера, а потом запустил код клиента и все работает замечательно, но почему-то всего лишь один раз, если запустить код клиента еще один раз, то лезут ошибки "socket_connect(): unable to connect [10061]: No connection could be made because the target machine actively refused it." Пробовал не закрывать соединение как на сервере так и на клиенте, код не работает, а точнее лезут опять же ошибки. Как запустить сервер так, чтобы я мог в любое время обращаться к нему? Если обращаться к серверу через HTML5 websocket нужно ли серверу отправлять заголовки о том, что он поддерживает сокеты? И в какой части кода они должны отправляться? Заранее очень благодарен за ответы!
Уважаемый админ ответьте пожалуйста на два предыдущих комента почему нормально срабатывает только один раз. Спс.
Ratchet
- отсутствие зависимостей
- наличие таймеров
В итоге я написал библиотеку для себя и поделился ею с сообществом на гитхабе. Сделал несколько демок (в том числе игру «танчики»). Переписал стороннюю игру (с разрешения авторов) с node.js на свою библиотеку. Делал нагрузочное тестирование. Демки работали годами без перезагрузки. Старался отвечать на тикеты в течения дня. Всё это показывало, что моя библиотека может быть использована на продакшене и многие её использовали.
Была единственная проблема. Мне хватало моей библиотеки для использования в своих проектах, а вот другим нет. Они хотели, чтобы я её развивал, а мне это было не нужно. Кому-то требовалась поддержка windows, а кому-то ssl, pg_notify, safari, pthreads и многое другое. Открытые тикеты с запросами на реализацию различного функционала висят годами.
Не так давно, я решил пересмотреть ещё раз, какие продукты могут быть полезны для пользователей моей библиотеки и был приятно удивлён, что кроме двух проектов, описанных выше появился ещё третий. Он полностью удовлетворял моим запросам и даже больше.
phpdaemon
Комментарии ( 2 ):
А способ взаимодействия клиента и сервера может называться протоколом? Например ftp.
В предыдущей статье я рассказывал про как создать сервер на PHP. Мы с Вами с использованием сокетов создали сервер на PHP. А в этой статье мы с Вами напишем клиента на PHP, который будет отправлять запрос на сервер и получать от него ответ.
Привожу код клиента на PHP:
Теперь у Вас есть минимальный набор знаний по работе с сокетами, а вообще тема очень интересная, поэтому Вы можете изучить её более детально. Вы можете создавать очень сложные клиент-серверные приложения, к котором Вы всегда сможете подключиться и отправлять самые различные запросы, которые сервер будет обрабатывать.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
Она выглядит вот так:
Workerman
Если загуглить «php websocket», то первая страница — это моя статья на Хабре, а вторая — «Ratchet», который кому-то может показаться сложным и он выберет из-за этого мою библиотеку или вообще откажется от идеи делать вебсокеты.
На главной странице проекта в гитхабе уже есть несколько примеров. Рассмотрим один из них:
Чтобы запустить пример, нужно установить workerwan: composer require workerman/workerman
Пример можно запустить с помощью команды php test.php start и в консоли мы увидим:
php test.php start
php test.php start -d -демонизировать скрипт
php test.php status
php test.php stop
php test.php restart
php test.php restart -d
php test.php reload
код сервера server.php:
код клиента client.html:
В общем, я выбрал для себя библиотеку Workerman и рекомендую переходить на неё пользователям моей библиотеки. Все примеры лежат на гитхабе.
Update: в комментариях рекомендуют swoole. Я натыкался на эту библиотеку ранее, но у меня сложилось ложное впечатление, что что она не поддерживает php7 и после этого она выпала из моего круга зрения. А зря. Интересная библиотека.
Не так давно меня попросили рассказать про сокеты на PHP. Вообще я планирую написать ещё несколько статей в ближайшее время по этой теме, а в этой статье я расскажу о том, что такое сокеты в PHP. Чтобы Вы уже могли понять, нужны они Вам или нет.
Сокет - это интерфейс взаимодействия клиента и сервера. Интерфейс - это, в свою очередь, правило, по которым происходит общение между клиентом и сервером. Чтобы стало понятнее, приведу пример из обычной жизни. Например, люди общаются с помощью слов на конкретном языке. Это наш с Вами интерфейс. В зависимости от входящих слов мы формируем образ у себя в голове, и отдаём ответ, в виде опять же слов. Другой пример, дельфины общаются в ультразвуком спектре, и это их интерфейс.
Надеюсь, про интерфейс теперь понятно, это правило взаимодействия. Теперь про клиента. Клиентом может выступать как человек, формирующий определённые запросы к серверу, так и программа, написанная на любом языке программирования, способном обмениваться данными с удалённым сервером. Сервер - это машина, ждущая подключения клиентов, принимающая от них запросы, и в зависимости от запросов, возвращающая ответ.
Кратко резюмирую, что же такое сокет: есть клиент, есть сервер, есть правила взаимодействия (интерфейс), клиент, согласно этим правилам, посылает запрос, а сервер данный запрос принимает и, согласно тем же правилам, даёт ответ.
Как видите, всё совсем не сложно. Очень здорово то, что клиент и сервер могут быть написаны на совсем разных языках программирования и могут находиться друг от друга за тысячи километров. Мы же с Вами будет писать и клиент, и сервер в будущих статьях на языке PHP.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
Она выглядит вот так:
User Contributed Notes 2 notes
You can easily extend the first example to handle any number of connections instead of jsut one
/* Permitir al script esperar para conexiones. */
set_time_limit ( 0 );
/* Activar el volcado de salida implícito, así veremos lo que estamo obteniendo
* mientras llega. */
ob_implicit_flush ();
$address = '127.0.0.1' ;
$port = 10000 ;
if (( $sock = socket_create ( AF_INET , SOCK_STREAM , SOL_TCP )) === false ) echo "socket_create() falló: razón: " . socket_strerror ( socket_last_error ()) . "\n" ;
>
if ( socket_bind ( $sock , $address , $port ) === false ) echo "socket_bind() falló: razón: " . socket_strerror ( socket_last_error ( $sock )) . "\n" ;
>
if ( socket_listen ( $sock , 5 ) === false ) echo "socket_listen() falló: razón: " . socket_strerror ( socket_last_error ( $sock )) . "\n" ;
>
//clients array
$clients = array();
do $read = array();
$read [] = $sock ;
$read = array_merge ( $read , $clients );
// Set up a blocking call to socket_select
if( socket_select ( $read , $write = NULL , $except = NULL , $tv_sec = 5 ) < 1 )
// SocketServer::debug("Problem blocking socket_select?");
continue;
>
// Handle new Connections
if ( in_array ( $sock , $read ))
if (( $msgsock = socket_accept ( $sock )) === false ) echo "socket_accept() falló: razón: " . socket_strerror ( socket_last_error ( $sock )) . "\n" ;
break;
>
$clients [] = $msgsock ;
$key = array_keys ( $clients , $msgsock );
/* Enviar instrucciones. */
$msg = "\nBienvenido al Servidor De Prueba de PHP. \n" .
"Usted es el cliente numero: < $key [ 0 ]>\n" .
"Para salir, escriba 'quit'. Para cerrar el servidor escriba 'shutdown'.\n" ;
socket_write ( $msgsock , $msg , strlen ( $msg ));
// Handle Input
foreach ( $clients as $key => $client ) < // for each client
if ( in_array ( $client , $read )) if ( false === ( $buf = socket_read ( $client , 2048 , PHP_NORMAL_READ ))) echo "socket_read() falló: razón: " . socket_strerror ( socket_last_error ( $client )) . "\n" ;
break 2 ;
>
if (! $buf = trim ( $buf )) continue;
>
if ( $buf == 'quit' ) unset( $clients [ $key ]);
socket_close ( $client );
break;
>
if ( $buf == 'shutdown' ) socket_close ( $client );
break 2 ;
>
$talkback = "Cliente < $key >: Usted dijo ' $buf '.\n" ;
socket_write ( $client , $talkback , strlen ( $talkback ));
echo " $buf \n" ;
>
Целью данной заметки является ознакомление PHP-разработчиков с возможностями межпроцессного взаимодействия в данном языке. Заметка не предполагает во всех деталях рассказать о каждой из возможностей, деталях реализации или показать рабочие примеры кода.
Поскольку задача распараллеливания рано или поздно появляется у любого программиста, то данная заметка была задумана отправной точкой, с которой можно начать своё путешествие в мир увлекательного геморроя процесса построения таких систем.
Так же, будет задета тема многопоточности в PHP, причём, именно потоков (Thread), так как до недавнего времени, PHP позволял (удобно) реализовать какое либо распараллеливание лишь благодаря Fork (не будем касаться извращений типа curl_multi_*, popen\fsockopen, Apache MPM и т.п.). Тема будет рассмотрена лишь в контексте IPC, поиск деталей реализации того или иного подхода оставляю читателям.
Ввиду всего вышеперечисленного, от читателя требуется некоторая подготовка, так как терминология будет разъясняться лишь в ключевых моментах, однако, текст обильно снабжён ссылками на необходимые статьи документации PHP, википедии и т.п., а так же, понимание того, что многие вещи нарочно упрощены, ввиду формата данного материала.
What does IPC look like?
Итак, что же такое межпроцессное взаимодействие?
Describe like IPC looks like!
План конспекта следующий:
0. PCNTL
Расширение реализует самый базовый функционал по работе с процессами, но нас интересует работа с сигналами UNIX, а конкретнее — функция pcntl_signal, которая позволяет установить обработчик сигналов. Этот подход самый малофункциональный из всех рассматриваемых, так как он не позволяет передавать данные. С помощью этого расширения можно, например, организовать старт\стоп воркеров, или считывание задач из буфера (файл, БД, память, etc.), или сигнализацию одной части системы другой о каком то событии.
Наиболее просто реализуема, есть множество примеров, и возможностей в применении, часто может более чем хватить для каких то не сильно сложных задач.
1. Sockets
Сокеты — (англ. socket — разъём) — название программного интерфейса для обеспечения обмена данными между процессами. Процессы при таком обмене могут исполняться как на одной ЭВМ, так и на различных ЭВМ, связанных между собой сетью. Сокет — абстрактный объект, представляющий конечную точку соединения.
Следует различать клиентские и серверные сокеты. Клиентские сокеты грубо можно сравнить с оконечными аппаратами телефонной сети, а серверные — с коммутаторами. Клиентское приложение (например, браузер) использует только клиентские сокеты, а серверное (например, веб-сервер, которому браузер посылает запросы) — как клиентские, так и серверные сокеты.
Пожалуй, это самый очевидный и наиболее известный способ реализации IPC, однако, и самый трудозатратный. Первый вариант — это создать брокер (сокет-сервер), клиентами-потоками коннектиться к нему. Тут вас ждёт увлекательный мир отладки неблокирующего ввода\вывода (а как вы хотели — писать блокирующий код?), а так же реализация многих тривиальных вещей типа обёрток над функциями расширения. Второй вариант проще, его можно применять для более простых реализаций: create_socket_pair, которая создаёт пару связанных сокетов, пример доступен по ссылке.
Использование сокетов для реализации IPC требует довольно серьёзного подхода и раскуривания мануалов, но к плюсам можно отнести возможность в будущем разнести элементы системы на различные сервера, не прибегая к существенным правкам кода. Так же, плюсом данной технологии является её универсальность: скажем, написать клиент на PHP, соединяющийся с C-шным сервером не сложно.
Так же, следует отменить и минусы: упомянутый выше неблокирующий IO. Так как данные будут поступать порциями, по следует хорошо подумать о механизме обеспечения их целостности, буферизации и обработке, которая бы не свела насмарку все преимущества неблокирующего ввода\вывода.
2. Shared Memory
Данное расширение позволяет полноценно работать с виртуальной памятью. Плюсы подхода в том, что он является наиболее быстрым (если быстродействие поставлено во главу угла приложения) и наименее ресурсозатратным. К тому же, его реализация не сопряжена с таким количеством подводных камней, как в предыдущем решении, да и сама технология не является трудноусваиваемой.
Вариантов использования множество: и общее пространство, и выделение блоков персонально под каждый поток\процесс, обработка данных так же упрощается ввиду чёткого определения размера блока. К недостаткам можно отнести некоторую сложность в удобной реализации такого взаимодействия: придётся пробрасывать адреса блоков в дочерние процессы (в виде параметров, при запуске pcntl_fork, с помощью файлов-маркеров etc.)
Данный подход является, пожалуй, наиболее распостранённым и предпочтительным, так как не требует больших трудозатрат в реализации, и является более универсальным.
3. Semaphore, Shared Memory and IPC
Семафоры могут пригодиться, когда потоки будут вынуждены работать с каким то общим ресурсом, скажем, вы написали файрволл, который будет при каждом запросе лезет в файлик с IP-адресами Роскомнадзора и делает с входящим запросом уличную магию. Файлик, понятное дело, обновляется каким то другим сервисным потоком, потому, недопустимо его чтение (или изменение), пока идёт процесс обновления, кем либо ещё. Теория работы семафоров проста, и примеров их реализации так же существует множество, потому, для тех, кто ещё не работал с этим типом блокировок, рекомендую ознакомиться, это поможет лучше понимать процессы построения взаимодействия между потоками.
4. Pthreads
И вот мы достигли segfault'а вершины эволюции как IPC, так и многопоточности в PHP.
Классный дядька по имени Joe Watkins написал расширение pthread, которое добавляет в PHP поддержку самой настоящей многопоточности. Буквально на днях (8.09.2013) вышла первая stable-версия (0.0.45), однако, автор в своём посте на Reddit весьма подробно раскрыл тему beta\stable релизов, потому, не заостряйте на этом внимание. Настоятельно рекомендую изучить всего его комментарии в теме, там много полезной информации о pthread.
В чём же достоинства? Во всём. Pthreads предоставляет крайне простой и удобный API для реализации любых ваших многопоточных фантазий. Тут вам и synchronize как в джаве, и события, и IPC с пробросом объктов! С ними, правда, не всё так гладко (см. примеры на гитхабе), и автор пишет, что эта проблема — не его рук дело, однако, с ресурсами сокетов ему всё же удалось сотворить чудо, и теперь, результаты socket_accept из главного потока можно всунуть в дочерний — поразительно! Достаточно разобрать примеры, чтобы понять, насколько всё просто и элегантно сделано.
Для запуска расширения необходимо собрать PHP в Thread-safe режиме, вот небольшой скрипт, который сделает всё за вас:
Does he look like a Pipe?
На этом, пожалуй, всё. Хотя язык и ограничен в своих возможностях IPC, тем не менее, он позволяет писать эффективные приложения с использованием различных подходов для реализации межпроцессного взаимодействия. Тем из вас, перед кем сейчас стоит задача реализации такого взаимодействия, рекомендую внимательно изучить все перечисленные в заметке способы, так как они не взаимозаменяемы, но эффективно дополняют друг друга.
P.S. Непосредственно к теме статьи это не относится, зато очень даже применимо к некоторым описанным здесь моментам, а именно, блокировании IO и несовершенстве событийной модели: рекомендую ознакомиться с расширениями Eio и Ev (автор обеих osmanov).
Давным-давно я публиковал статью на хабре, как написать свой вебсокет-сервер с нуля. Статья переросла в библиотеку. Несколько месяцев я занимался её развитием, ещё несколько лет — поддержкой и багфиксом. Написал модуль интеграции с yii2. Какой-то энтузиаст написал интеграцию с laravel. Моя библиотека совместима с php7. Недавно я решил отказаться от её дальнейшей поддержки (причины ниже), поэтому хочу помочь её пользователям перейти на другую библиотеку.
Прежде чем начать писать свой вебсокет-сервер, я выбирал из готовых продуктов, и на тот момент их было всего два: phpdaemon и ratchet.
Соединение TCP/IP
\n" ;/* Создаём сокет TCP/IP. */
$socket = socket_create ( AF_INET , SOCK_STREAM , SOL_TCP );
if ( $socket === false ) echo "Не удалось выполнить socket_create(): причина: " . socket_strerror ( socket_last_error ()) . "\n" ;
> else echo "OK.\n" ;
>
echo "Пытаемся соединиться с ' $address ' на порту ' $service_port '. " ;
$result = socket_connect ( $socket , $address , $service_port );
if ( $result === false ) echo "Не удалось выполнить socket_connect().\nПричина: ( $result ) " . socket_strerror ( socket_last_error ( $socket )) . "\n" ;
> else echo "OK.\n" ;
>
$in = "HEAD / HTTP/1.1\r\n" ;
$in .= "Host: www.example.com\r\n" ;
$in .= "Connection: Close\r\n\r\n" ;
$out = '' ;
echo "Отправляем HTTP-запрос HEAD. " ;
socket_write ( $socket , $in , strlen ( $in ));
echo "OK.\n" ;
echo "Читаем ответ:\n\n" ;
while ( $out = socket_read ( $socket , 2048 )) echo $out ;
>
echo "Закрываем сокет. " ;
socket_close ( $socket );
echo "OK.\n\n" ;
?>
Читайте также: