работа с сокетами php
Примеры
Пример #1 Пример использования сокетов: Простой сервер TCP/IP
Этот пример показывает работу простого сервера. Измените переменные address и port в соответствии с вашими настройками и выполните. Затем вы можете соединиться с сервером с командой, похожей на: telnet 192.168.1.53 10000 (где адрес и порт должны соответствовать вашим настройкам). Всё, что вы наберёте на клавиатуре, будет затем выведено на сервере и отправлено вам обратно. Для отключения наберите ‘выход’.
/* Позволяет скрипту ожидать соединения бесконечно. */
set_time_limit ( 0 );
/* Включает скрытое очищение вывода так, что мы видим данные
* как только они появляются. */
ob_implicit_flush ();
$address = ‘192.168.1.53’ ;
$port = 10000 ;
Пример #2 Пример использования сокетов: Простой клиент TCP/IP
Этот пример показывает использование простого одноразового HTTP-клиента. Он просто соединяется со страницей, отправляет запрос HEAD, выводит ответ и завершает работу.
Соединение TCP/IP
/* Получаем IP-адрес целевого хоста. */
$address = gethostbyname ( ‘www.example.com’ );
User Contributed Notes 2 notes
You can easily extend the first example to handle any number of connections instead of jsut one
#!/usr/bin/env php
( E_ALL );
/* 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 ;
//clients array
$clients = array();
Функции сокета
Содержание
User Contributed Notes 19 notes
After many non-sleep nights I got the most simple multi-client server written in PHP that really works. Ctrl+C and Ctrl+V. use as command line to test it. Enjoy it.
// Set time limit to indefinite execution
set_time_limit ( 0 );
// Set the ip and port we will listen on
$address = ‘10.203.9.67’ ;
$port = 6901 ;
Planning on sending integer values through as socket, I was surprised to find PHP only supports sending strings.
I came to the conclusion the only way to do it would be to create a string that would evaluate to the same byte values as the integer I wanted to send. So (after much messing about) I created a couple of functions: one to create this ‘string’ and one to convert a received value back to an integer.
A multicast server can be written badly as follows:
Checking the return types is needed, but this does allow for you to multicast from php code.
I have searched long and hard for a ping script that does NOT use EXEC() or SYSTEM(). So far, I have found nothing, so I decided to write my own, which was a task to say the least.
First off, I would like to thank Khaless for their checksum function, converting it from C looked like a task in itself.
function Build_Packet ()
<
$data = «abcdefghijklmnopqrstuvwabcdefghi» ; // the actual test data
$type = «\x08» ; // 8 echo message; 0 echo reply message
$code = «\x00» ; // always 0 for this program
$chksm = «\x00\x00» ; // generate checksum for icmp request
$id = «\x00\x00» ; // we will have to work with this later
$sqn = «\x00\x00» ; // we will have to work with this later
?>
Hope this saves some troubles.
WebSocket сервер на PHP
Протокол WebSocket предназначен для решения разных задач и снятия ограничений обмена данными между браузером и сервером. Он позволяет пересылать любые данные, на любой домен, безопасно и почти без лишнего сетевого трафика. Для установления соединения WebSocket клиент и сервер используют протокол, похожий на HTTP. Клиент формирует особый HTTP-запрос, на который сервер отвечает определенным образом.
Простой сокет-сервер
В первую очередь надо в файле php.ini расскомментировать строку, позволяющую работать с сокетами и перезапустить сервер:
Вот как выглядит простейший сокет-сервер:
Запустим его в работу:
Попробуем пообщаться с сервером с помощью telnet :
И видим сообщение от сервера:
Наш сервер в другом окне тоже встрепенулся:
WebSocket сервер
Протокол WebSocket работает над TCP. Это означает, что при соединении браузер отправляет по HTTP специальные заголовки, спрашивая: «Поддерживает ли сервер WebSocket?». Если сервер в ответных заголовках отвечает «Да, поддерживаю», то дальше HTTP прекращается и общение идёт на специальном протоколе WebSocket, который уже не имеет с HTTP ничего общего.
Здесь GET и Host — стандартные HTTP-заголовки, а Upgrade и Connection указывают, что браузер хочет перейти на WebSocket.
Для тестирования работы сервера нам нужен клиент:
Проверим его в работе. Открываем HTML-страницу в браузере и заполняем первое поле «Сервер»:
Это гарантированно работающий WebSocket echo-сервер, которые отправляет все сообщения обратно. Жмем кнопку «Установить соединение», набираем текст сообщения в поле «Сообщение», жмем кнопку «Отправить сообщение»:
А теперь код WebSocket сервера на PHP:
Для тестирования напишем небольшой PHP-скрипт, который запускает в работу сервер и все сообщения клиента отправляет обратно (echo-сервер):
Запускаем скрипт в работу:
Еще один пример использования сервера — клиент отправляет команды, а сервер их выполняет:
Альтернативная реализация WebSocket сервера с использованием функций для работы с потоками:
PHP: Программирование сокетов
Сокеты представляют собой чрезвычайно удобную, но в то же время плохо понятую технологию взаимодействия между двумя процессами в сети. Эти процессы могут существовать на одной и той же машине, общаясь друг с другом через локальный сокет, предназначенный для взаимодействия между процессами, либо на разных машинах через Internet. Хотя тема сокетов очень обширна, в данной статье представлены основы, которые необходимы для использования расширений РНР, предназначенных для написания собственных серверов и клиентов сокетов.
�?мейте в виду, что примеры, приведённые далее в этой статье, разработаны для запуска непосредственно из окружения оболочки с использованием версии РНР командной строки. Хотя их можно запустить в Web-браузере, делать это не рекомендуется. В случае сценариев, которые создают серверы сокетов, их применение можно продемонстрировать с помощью любых программ, способных устанавливать сетевое соединение через сокеты, например, telnet (что, собственно, и рекомендуется).
Основы сокетов
Сокеты могут быть надежными, выполняющими все необходимое для обеспечения передачи данных из точки А в точку В (TCP), либо ненадежными, когда данные передаются без гарантии доставки (UDP).
Сокеты также бывают «блокирующими» и «неблокирующими». Блокирующие сокеты заставляют ваше приложение ожидать до тех пор, пока данные станут доступны, в то время как неблокирующие сокеты этого не делают. Хотя, как будет показано далее, все сокеты двунаправлены, все же существует разница между сокетами клиента и сервера.
Мы с вами рассмотрим ТСР-сокеты Internet, поскольку они наиболее широко используются на сегодняшний день. Тем не менее, концепции и примеры кода, приведенные здесь, применимы к большинству операций с сокетами.
Создание нового сокета
Независимо от типа создаваемого сокета (клиентский или серверный), все они инициализируются одинаковым способом — с помощью функции socket_create(). Синтаксис этой функции выглядит следующим образом:
В результате выполнения эта функция либо возвращает ресурс, представляющий созданный сокет, либо булевское значение false в случае ошибки.
Константы доменов для сокеткых соединений
Константа | Описание |
---|---|
AF_INET | Протокол Internet IPv4 |
AF_INET6 | Протокол Internet IPv6 |
AF_UNIX | Локальное межпроцессное взаимодействие |
После того, как домен установлен, нужно определить Т�?П подключения для создаваемого сокета. Эти типы перечислены в следующей таблице:
Константы типов сокетов
Константа | Описание |
---|---|
SOCK_STREAM | Последовательный надежный двунаправленный поток, основанный на подключении. �?спользуется наиболее часто. |
SOCK_DGRAM | Ненадежный сокет, без подключения, передающий данные фиксиро ванной длины. Очень хорош для потоков данных, в которых надеж ность не критична. |
SOCK_SEQPACKET | Подобен потоковым сокетам за исключением того, что данные пере даются н принимаются в виде пакетов фиксированной длины. |
SOCK_RAW | Неформатированное сокетное подключение, удобное для выполне ния операций ICMP (Internet Control Message Protocol — протокол управляющих сообщений Internet), таких как trace, ping и так далее. |
SOCK_RDM | Надежный, по непоследовательный сокет, подобный SOCK DGRAM. |
Как видите, существует множество опций при выборе типа создаваемых сокетов. Вообще большинство сокетных соединений устанавливается с помощью сокетов SОСК_STREAM или SOCK_DGRAM. Учитывая очевидную полноту SOCK_STREAM (большая часть Internet работает по этому типу сокетов через TCP), может быть не совсем понятно, зачем нужны сокеты типа SOCK_DGRAM (используемые с протоколом UDP).
В конце концов, почему вообще вам может понадобиться «ненадежный» способ передачи данных? Ответ становится очевидным, когда возникает необходимость в получении постоянного потока данных, который обрабатывается в реальном времени, от сервера к клиенту. Поскольку для приложений подобного типа потерянные пакеты несущественны (поскольку такие приложения имеют дело с данными, привязанными ко времени, которые быстро устаревают), нет необходимости в повторной отправке пакетов.
Мы будем испольэовать сокеты Internet IPv4 типа SOCK_STREAM, работающие через соединения SOL_TCP (TCP), После того, как ресурс сокета создан, он может быть уничтожен с помощью функции socket_close(), имеющей следующий синтаксис:
socket_close($socket);
Ошибки сокетов
socket_last_error($socket);
socket_strerror($error_code);
Создание клиентских сокетов.
Создание сокета, готового для подключения к другому сокету в Internet, выполняется с помощью функции socket_connect ():
$socket — это сокет для записи данных;
Когда эта функция выполняется, она отправляет содержимое буфера через подключенный сокет и возвращает количество записанных байт, либо булевское значение false в случае возникновения ошибки.
Для чтения данных из сокета применяется функция socket_read<) со следующим синтаксисом:
Константы типа для socket_read()
Константа | Описание |
---|---|
PHP_BINARY_READ | �?нтерпретировать данные как бинарные (поумолчанию). |
PHP_NORMAL_READ | Читать данные заданной длины, либо пока не встретится символ новой строки (\r или \n). |
В листинге ниже представлен пример использования сокетов для извлечения индексной страницы Web-сайта, в него включено все, что рассматривалось выше. �?звлечение индексной страницы осуществляется отправкой простого GET-запроса HTTP 1.0 с последующим чтением результата в переменную.
Создание серверных сокетов
Когда осуществляется привязка к адресу, убедитесь, что ваш сокет не допустит подключений к чему-либо другому, кроме указанного адреса и порта! Это означает, что привязка сокета к локальному хосту (127.0.0.1) позволит вашему сокету принимать топько покальные подключения.
Второй шаг: настроить сокет на прослушивание трафика на предмет попыток подключения к нему. Это делается с помощью функции socket_listen():
Третий и последний шаг в создании серверного сокета — дать команду на прием входящих подключений. Это делается функцией socket_accept ():
socket_accept($socket);
В листинге ниже создается простой сокетный сервер, принимающий единственное подключение, максимум 1024 байта входного потока и отображающий этот поток пользователю.
Создание простого сервера на основе сокета
У меня на компе этот скрипт лежит в папке денвера по пути: C:\WebServers\home\app.loc\www\sockets\test.php
Теперь, если запустить наш скрипт из командной строки таким макаром: C:\WebServers\home\app.loc\www\sockets>php test.php В командной строке мы увидим следующее:
Сервер в ответ пришлёт нам наш же запрос + заголовки:
В командной строке мы увидим новые данные
Чтобы создать сервер, сокеты которого ведут прослушивание на портах с номерами ниже 1000, данный пользователь должен иметь в системе административные права. Также следует отметить, что приведенный выше сценарий не завершит работу до тех пор, пока не будет установлено соединение, что может создать впечатление «зависания».
Одновременная работа с несколькими сокетами
В листинге, на предыдущей странице был представлен сервер на базе сокетов. Однако он не слишком удобен для реальных, целей, поскольку к нему может выполняться только одно подключение одновременно. Чтобы создать более удобный сервер сокетов, необходимо научиться работать одновременно с множеством сокетов. Чтобы сделать это, понадобится функция socket_select (), синтаксис которой выглядит следующим образом:
В случае ошибочного завершения socket_select() возвращает булевское значение false.
Для использования этой функции в реальном приложении первым делом должен быть создан сокет, представляющий сервер в целом. Этот главный сокет будет привязан к определенному адресу и порту и начнет прослушивание подключений.
Этот новый подключенный сокет затем подвергается мониторингу через тот же вызов socket_select() (за счет добавления его к тому же массиву, куда уже добавлен наш главный сокет) и реализуется логика приложения, обеспечивающая функциональность нашего сервера. В листинге ниже представлен работающий пример простого сервера, принимающего настраиваемое число подключений.
Создание многосортного сервера на РНР
В листинге выше вскрыты некоторые ограничения сценарного механизма РНР, которые требуют несколько более сложного обходного пути в форме вызова socket_select():
$NULL = NULL;
�? последующей ее передачи функции socket_select().
Функции сокетов
Расширение сокетов реализует низкоуровневый интерфейс функций сообщений через сокеты на основе популярных BSD-сокетов, давая возможность работать и как серверу сокетов, и как клиенту.
Эти функции всегда доступны.
Замечание: Поддержка IPv6 была добавлена в PHP 5.0.0.
При использовании этих функций важно помнить, что, хотя многие из них имеют имена, аналогичные их двойникам языка C, они часто имеют разные объявления. Обязательно прочтите описания, чтобы исключить конфликты.
Те, кто мало знаком с программированием сокетов, могут найти соответствующий материал на Unix man-страницах; в web также имеется большое количество учебной информации о программировании сокетов на C, большая часть которой может быть применена, с некоторыми изменениями, для программирования сокетов в PHP. UNIX Socket FAQ может стать хорошим началом.
Пример 1. Сокет: Простой TCP/IP-сервер
Это пример простого talkback-сервера. Измените переменные address и port для ваших установок и запустите. Вы можете затем соединиться с сервером командой вроде этой: telnet 192.168.1.53 10000 (где address и port соответствуют вашим установкам). Всё, что вы напечатаете, будет затем выведено на стороне сервера и возвращено вам обратно. Для отсоединения введите ‘quit’.
/* Позволить сценарию зависнуть вокруг ожидания подключений */
set_time_limit ( 0 );
$address = ‘192.168.1.53’ ;
$port = 10000 ;
Пример 2. Сокет: простой TCP/IP-клиент
Это простой HTTP-клент. Он соединяет со страницей, отправляет HEAD-запрос, возвращает ответ и выходит.
TCP/IP Connection
/* Get the IP address for the target host. */
$address = gethostbyname ( ‘www.example.com’ );