◆ Основы сокетов
PHP использует библиотеку сокетов Berkley для создания соединений. Сокет — это не что иное, как структура данных. Вы используете эту структуру данных сокета для запуска сеанса между клиентом и сервером. Этот сервер всегда прослушивает и готовится создать новый сеанс. Когда клиент подключается к серверу, он открывает порт, на котором сервер прослушивает сеанс. В это время сервер принимает запрос на соединение клиента и затем выполняет цикл. Теперь клиент может отправлять информацию на сервер, а сервер может отправлять информацию клиенту.
Чтобы создать сокет, вам нужны три переменные: протокол, тип сокета и тип общедоступного протокола. При создании сокета можно выбрать один из трех протоколов. Продолжите читать ниже, чтобы получить подробное описание протокола.
Определение типа общедоступного протокола является важным элементом соединения. В таблице ниже мы рассмотрим распространенные типы протоколов.
Таблица 1. Имя протокола/описание константы
AF_INET Это протокол, используемый большинством сокетов, использующий TCP или UDP для передачи, и используемый в адресах IPv4.
AF_INET6 аналогичен приведенному выше, но используется для адресов IPv6.
Локальный протокол AF_UNIX, используемый в системах Unix и Linux. Обычно используется, когда клиент и сервер находятся на одном компьютере. Таблица 2: Имя типа сокета/описание константы.
SOCK_STREAM Этот протокол представляет собой последовательное, надежное соединение на основе потока байтов с интеграцией данных. Это наиболее часто используемый тип сокета. Этот сокет использует TCP для передачи.
SOCK_DGRAM Этот протокол представляет собой вызов передачи фиксированной длины без установления соединения. Этот протокол ненадежен и для своих соединений использует UDP.
SOCK_SEQPACKET Этот протокол представляет собой двухлинейное надежное соединение, которое отправляет для передачи пакеты данных фиксированной длины. Этот пакет должен быть полностью принят, прежде чем его можно будет прочитать.
SOCK_RAW Этот тип сокета обеспечивает единый доступ к сети. Этот тип сокета использует общедоступный протокол ICMP. (ping и трассировка используют этот протокол)
SOCK_RDM Этот тип используется редко и не реализован в большинстве операционных систем. Он предоставляется для использования на уровне канала передачи данных и не гарантирует порядок пакетов. Таблица 3: Имя/описание константы публичного протокола.
ICMP Протокол управляющих сообщений Интернета, в основном используемый на шлюзах и хостах для проверки состояния сети и сообщения об ошибках.
Протокол пользовательских дейтаграмм UDP, который является ненадежным протоколом передачи без установления соединения.
Протокол управления передачей TCP, который является наиболее часто используемым надежным общедоступным протоколом, может гарантировать, что пакет данных дойдет до получателя. Если в процессе передачи произойдет ошибка, пакет с ошибкой будет отправлен повторно.
Теперь, когда вы знаете три элемента, которые генерируют сокет, мы используем функцию socket_create() в PHP для создания сокета. Эта функция socket_create() требует трех параметров: протокола, типа сокета и общедоступного протокола. Функцияocket_create() возвращает тип ресурса, содержащий сокет, если она выполняется успешно. В случае сбоя она возвращает false.
Resourcesocket_create (протокол int, intocketType, int commonProtocol);
Теперь вы создаете сокет, и что дальше? PHP предоставляет несколько функций для управления сокетами. Вы можете привязать сокет к IP-адресу, прослушивать сообщения сокета и принимать сокет. Теперь давайте рассмотрим пример, чтобы понять, как функция генерирует, принимает и прослушивает сокет;
<?php
$commonProtocol = getprotobyname("tcp");//Используйте имя публичного протокола, чтобы получить тип протокола
$socket =ocket_create(AF_INET, SOCK_STREAM, $commonProtocol);//Создаем сокет и возвращаем экземпляр ресурса сокета
socket_bind($socket, 'localhost', 1337);//Привязываем сокет к локальному компьютеру
socket_listen($socket);//Прослушиваем все входящие соединения сокетов
// Еще больше функций сокетов
?>
В приведенном выше примере создается ваша собственная серверная часть. Первая строка примера,
$commonProtocol = getprotobyname("tcp");
Используйте имя общедоступного протокола, чтобы получить тип протокола. Здесь используется общедоступный протокол TCP. Если вы хотите использовать протокол UDP или ICMP, вам следует изменить параметры функции getprotobyname() на «udp» или «icmp». Другой альтернативой является указание SOL_TCP или SOL_UDP в функцииocket_create() вместо использования функции getprotobyname().
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
Вторая строка примера создает сокет и возвращает экземпляр ресурса сокета. После того как у вас есть экземпляр ресурса сокета, вы должны привязать сокет к IP-адресу и порту.
Socket_bind ($ Socket, 'localhost', 1337);
Здесь вы привязываете сокет к локальному компьютеру (127.0.0.1) и привязываете сокет к своему порту 1337. Затем вам нужно прослушивать все входящие соединения сокетов.
Socket_listen ($ сокет);
После четвертой строки вам необходимо понять все функции сокетов и их использование.
Таблица 4: Описание названия функции функции сокета
socket_accept() принимает соединение Socket
socket_bind() привязывает сокет к IP-адресу и порту
socket_clear_error() очищает ошибку сокета или последний код ошибки
ocket_close() закрывает ресурс сокета
socket_connect() запускает соединение через сокет
ocket_create_listen() открывает сокет, прослушивающий указанный порт
ocket_create_pair() генерирует пару неразличимых сокетов в массив
ocket_create() генерирует сокет, что эквивалентно созданию структуры данных сокета.
ocket_get_option() Получить параметры сокета
socket_getpeername() Получает IP-адрес удаленного аналогичного хоста.
socket_getsockname() получает IP-адрес локального сокета
socket_iovec_add() добавляет новый вектор в массив разброса/агрегирования.
socket_iovec_alloc() Эта функция создает структуру данных iovec, которая может отправлять, получать, читать и записывать.
Socket_iovec_delete() удаляет выделенный iovec
Socket_iovec_fetch() возвращает данные указанного ресурса iovec
socket_iovec_free() освобождает ресурс iovec
socket_iovec_set() устанавливает новое значение данных iovec
ocket_last_error() получает последний код ошибки текущего сокета
Socket_listen() прослушивает все соединения из указанного сокета
Socket_read() считывает данные указанной длины
Socket_readv() считывает данные из массива разброса/агрегирования.
socket_recv() завершает передачу данных из сокета в кеш
Socket_recvfrom() принимает данные из указанного сокета. Если он не указан, по умолчанию используется текущий сокет.
Socket_recvmsg() получает сообщения от iovec
Socket_select() множественный выбор
Socket_send() Эта функция отправляет данные в подключенный сокет.
socket_sendmsg() отправляет сообщение в сокет
Socket_sendto() отправляет сообщение в сокет по указанному адресу.
socket_set_block() переводит сокет в режим блокировки
socket_set_nonblock() Установить сокет в неблокирующий режим
socket_set_option() устанавливает параметры сокета
Socket_shutdown() Эта функция позволяет закрыть чтение, запись или указанный сокет.
Socket_strerror() возвращает подробную информацию об ошибке с указанным номером ошибки.
ocket_write() записывает данные в кеш сокета
Socket_writev() записывает данные в разбросанные/агрегированные массивы. Все вышеперечисленные функции связаны с сокетами в PHP. Чтобы использовать эти функции, вам необходимо открыть свой сокет. Если вы его не открывали, отредактируйте файл php.ini и удалите его. следующий комментарий перед этой строкой:
расширение = php_sockets.dll
Если вы не можете удалить комментарий, используйте следующий код для загрузки библиотеки расширений:
<?php
if(!extension_loaded('сокеты')) {
if(strtoupper(substr(PHP_OS, 3)) == «WIN») {
дл('php_sockets.dll');
}еще{
дл('sockets.so');
}
}
?>
Если вы не знаете, открыт ли ваш сокет, вы можете использовать функцию phpinfo(), чтобы определить, открыт ли сокет. Вы можете проверить, открыт ли сокет, проверив информацию phpinfo.
Просмотр информации phpinfo() о сокете. ◆ Создание сервера. Теперь давайте улучшим первый пример. Вам необходимо прослушивать определенный сокет и обрабатывать соединения пользователей.
<?php
$commonProtocol = getprotobyname("tcp");
$socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol);
Socket_bind ($ Socket, 'localhost', 1337);
Socket_listen ($ сокет);
//Принимаем любые входящие соединения с сервером
$connection = socket_accept($socket);
если ($ соединение) {
socket_write($connection, "Вы подключились к сокету...nr");
}
?>
Для запуска этого примера вам следует использовать командную строку. Причина в том, что здесь будет создан сервер, а не веб-страница. Если вы попытаетесь запустить этот сценарий с помощью веб-браузера, есть большая вероятность, что он превысит 30-секундный лимит. Вы можете использовать приведенный ниже код, чтобы установить бесконечное время выполнения, но для запуска рекомендуется использовать командную строку.
set_time_limit (0);
Просто протестируйте этот скрипт в командной строке:
Пример PHP.exe01_server.php
Если вы не указали путь к интерпретатору php в переменных среды вашей системы, вам нужно будет указать путь к php.exe. Когда вы запустите сервер, вы можете протестировать его, подключившись к порту 1337 через telnet.
Есть три проблемы с серверной частью, описанной выше: 1. Он не может принимать несколько соединений. 2. Он выполняет только одну команду. 3. Вы не можете подключиться к этому серверу через веб-браузер.
Эту первую проблему решить проще: вы можете каждый раз использовать приложение для подключения к серверу. Но следующая проблема заключается в том, что вам нужно использовать веб-страницу для подключения к серверу, что сложнее. Вы можете заставить свой сервер принять соединение, записать некоторые данные клиенту (если он должен их записать), закрыть соединение и дождаться следующего соединения.
Улучшите предыдущий код и сгенерируйте следующий код для создания нового сервера:
<?php
// Настраиваем наш сокет
$commonProtocol = getprotobyname("tcp");
$socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol);
socket_bind($socket, 'localhost', 1337); //socket_bind() привязывает сокет к IP-адресу и порту
Socket_listen ($ сокет);
//Инициализируем буфер
$buffer = "НЕТ ДАННЫХ";
в то время как (истина) {
// Принимаем любые соединения, входящие в этот сокет
$connection =ocket_accept($socket);//socket_accept() принимает соединение Socket
printf("Сокет подключенrn");
// Проверяем, есть ли что-нибудь в буфере
if($buffer != ""){
printf("Что-то есть в буфере...отправка данных...rn");
socket_write($connection, $buffer . "rn"); //socket_write() записывает данные в кеш сокета
printf("Записано в сокетrn");
}еще {
printf("Нет данных в буфереrn");
}
//Получаем ввод
while($data =ocket_read($connection, 1024, PHP_NORMAL_READ))//socket_read() считывает данные указанной длины
{
$буфер = $данные;
socket_write($connection, "Информация полученаrn");
printf("Буфер: ". $buffer. "rn");
}
Socket_close($connection); //socket_close() закрывает ресурс сокета
printf("Сокет закрытrnrn");
}
?>
Что должен делать этот сервер? Он инициализирует сокет и открывает кеш для отправки и получения данных. Он ожидает соединения и как только соединение установлено, на экране на стороне сервера печатается «Сокет подключен». Этот сервер проверяет буфер и, если в буфере есть данные, отправляет их на подключенный компьютер. Затем он отправляет сообщение о принятии этих данных. Как только оно принимает сообщение, оно сохраняет его в данных, уведомляет подключенный компьютер о сообщении и, наконец, закрывает соединение. Когда соединение закрывается, сервер начинает обработку следующего соединения.
◆ Легко создать клиент для решения второй проблемы. Вам нужно сгенерировать php-страницу, подключиться к сокету, отправить некоторые данные в ее кеш и обработать их. Затем вас ждут обработанные данные, и вы можете отправить свои данные на сервер. При другом клиентском соединении он будет обрабатывать эти данные.
Следующий пример демонстрирует использование сокетов:
<?php
// Создаем сокет и подключаемся
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$connection = socket_connect($socket,'localhost', 1337);
while($buffer =ocket_read($socket, 1024, PHP_NORMAL_READ)) {
if($buffer == "НЕТ ДАННЫХ") {
echo("<p>НЕТ ДАННЫХ</p>");
перерыв;
}еще{
// Делаем что-то с данными в буфере
echo("<p>Данные буфера: " . $buffer . "</p>");
}
}
echo("<p>Запись в сокет</p>");
// Записываем тестовые данные в наш сокет
if(!socket_write($socket, «НЕКОТОРЫЕ ДАННЫЕrn»)){
echo("<p>Ошибка записи</p>");
}
// Читаем любой ответ из сокета
while($buffer =ocket_read($socket, 1024, PHP_NORMAL_READ)){
echo("<p>Отправленные данные: НЕКОТОРЫЕ ДАННЫЕ<br> Ответ:" . $buffer . "</p>");
}
echo("<p>Чтение из сокета завершено</p>");
?>
В этом примере кода показано подключение клиента к серверу. Клиент читает данные. Если это первое соединение в этом цикле, сервер отправит обратно клиенту сообщение «НЕТ ДАННЫХ». Если это произойдет, клиент окажется на вершине соединения. Клиент отправляет свои данные на сервер, данные отправляются на сервер, и клиент ждет ответа. Как только ответ получен, он записывает ответ на экран.