Содержание
Функция fsockopen()
Функцию fopen() можно использовать и для открытия сетевых соединений с файлами на других хостах в Сети. Но функция fopen() позволяла работать только с содержимым файла, переданного по протоколу HTTP.
По HTTP, кроме "тела" документа, передаются заголовки, посланные сервером. Функция fsockopen() позволяет "Добраться" и до заголовков, иногда это бывает полезно.
int fsockopen(string $host, int $port [,int &$errno] [,string &$errstr])
Эта функция работает аналогично fopen(), но только устанавливает сетевое соединение с указанным хостом $host и программой, закрепленной на нем за портом $port. Она возвращает файловый дескриптор, с которым затем могут быть выполнены обычные операции: fread(), fwrite(), fgets(), feof(). В случае ошибки возвращается false и, если заданы параметры-переменные $errno и $errstr, то в них записываются соответственно номер ошибки (не равный нулю) и текст сообщения об ошибке.
Если функция вернула false, но $errno тем не менее сбросилась в 0, это скорее всего означает, что произошла ошибка инициализации сокета. Например, такое может произойти, если в Windows не установлен требуемый протокол TCP/IP.
По умолчанию сокет (соединение) открывается в режиме чтения и записи, используя блокирующий режим передачи. Вы можете переключить режим в неблокирующий, если вызовете функцию socket_set_blocking() (см. ниже заголовок: Функция socket_set_blocking).
В примере из листинга 1 был "проэмулирован" браузер, послав в порт 80 удаленного хоста HTTP-запрос GET и получен весь ответ вместе с заголовками. Мы используем функцию HtmlSpecialChars(), чтобы вывести HTML-код документа в текстовом формате.
Листинг 1. "Эмуляция" браузера
"; // Отключаемся от сервера fclose($fp); ?>
Мы можем использовать не только 80-й порт. Функция fsockopen() универсальна, и позволяет подключаться к telnet-порту, к FTP.
Функция socket_set_blocking
int socket_set_blocking(int $sd, int $mode)
Эта функция устанавливает блокирующий или неблокирующий режим для соединения, открытого ранее при помощи fsockopen(). В режиме блокировки ($mode=true) функции чтения будут "засыпать", пока передача данных не завершится. Таким образом, если данных много, или же произошел "затор" в сети, ваша программа остановится и будет дожидаться выхода из функции чтения.
В режиме запрета блокировки ($mode=false) функции наподобие fgets() будут сразу же возвращать управление в программу, даже если через соединение не было передано еще ни одного байта данных. Таким образом, считывается ровно столько информации, сколько доступно на данный момент. Определить, что данные кончились, можно с помощью функции feof(), как это было сделано в примере из листинга 1.
Открытие соединения через сокет
РНР не ограничивается взаимодействием с файлами и процессами, вы также можете устанавливать соединения через сокеты. Сокет (socket) представляет собой программную абстракцию, позволяющую устанавливать связь с различными службами другого компьютера.
Функция fsockopen( ) устанавливает сокетное соединение с сервером в Интернете используя протокол TCP или UDP.
Синтаксис функции fsockopen( ):
int fsockopen (string узел, int порт [, int код_ошибки [, string текст_ошибки [, int тайм-аут]]])
Необязательные параметры код_ошибки и текст_ошибки содержат информацию, которая будет выводиться в случае неудачи при подключении к серверу. Оба параметра должны передаваться по ссылке. Третий необязательный параметр, тайм-аут, задает продолжительность ожидания ответа от сервера (в секундах). В листинге 2 продемонстрировано применение функции fsockopen( ) для получения информации о сервере.
Функция socket_set_b1ocki ng( ) позволяет установить контроль над тайм-аутом для операций с сервером:
socket_set_blocking(int манипулятор, boolean режим)
Параметр манипулятор задает открытый ранее сокет, а параметр режим выбирает режим, в который переключается сокет (TRUE для блокирующего режима, FALSE для неблокирующего режима). Пример использования функций fsockopen( ) и socket_set_blocking( ) приведен в листинге 2.
Листинг 2. Использование функции fsockopen() для получения информации о сервере
В результате выполнения кода листинга 2 выводится следующий результат:
НТТР/1.0 200 OK
Server: Microsoft-IIS/4.0
Content-location: http://www.soft.com/
Date: Sat. 19 Aug 2000 21:02:23 GMT
Content-Type: text/html
Last-Modified: Wed. 19 Jul
Content-Length: 1234
Функция pfsockopen( )
Функция pfsockopen( ) представляет собой устойчивую (persistent) версию fsockopen( ). Соединение не будет автоматически разорвано по завершении сценария, в котором была вызвана функция. Синтаксис функции pfsockopen( ):
int pfsockopen (string узел, int порт [, int код_ошибки [, string текст _ошибки [, int тайм-аут]]])
В зависимости от конкретных целей вашего приложения может оказаться удобнее использовать pfsockopen( ) вместо fsockopen( ).
PHP позволяет скрипту соединиться с помощью сокетов к любому хосту и порту с помощью функции fsockopen. Функция fsockopen предназначена для соединения клиента с сервером. Она очень удобна, поскольку является универсальной и объединяет в себе те функции, которые есть в PHP для работы с сокетами.
Пример обмена http заголовками между браузером и сервером.
——————————————
Запрос клиента:
GET /index.php HTTP/1.1
Host: master-web.com.ua
User-Agent: Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9b5) Gecko/2008050509 Firefox/3.0b5
Accept: text/html
Connection: close
——————————————
Ответ сервера:
HTTP/1.0 200 OK
Date: Wed, 11 Feb 2009 11:20:59 GMT
Server: Apache
X-Powered-By: PHP/5.2.4-2ubuntu5wm1
Last-Modified: Wed, 11 Feb 2009 11:20:59 GMT
Content-Language: ru
Content-Type: text/html; charset=utf-8
Content-Length: 1234
Connection: close
Запрос клиента начинается с команды GET. Каждый сервер должен поддерживать как минимум две команды GET и HEAD. Посмотрите какие еще существуют основные команды:
GET — используется для запроса содержимого указанного ресурса (страницы). В результате этой команды сервер должен выполнить запрос и возвратить ответ. Как правило, все клиенты (браузеры) для получения страницы сайта по url используют get.
HEAD — аналогичен методу GET, за исключением того, что в ответе сервера отсутствует тело. Другими словами обратно Вы получите только заголовок ответа сервера, но не код страницы.
POST — применяется для передачи пользовательских данных заданному ресурсу. Эти данные могут быть в виде файла или просто текста. Как правило, название переменной и ее значение.
TRACE — возвращает полученный запрос так, что клиент может увидеть, что промежуточные сервера добавляют или изменяют в запросе.
Разбираем запрос клиента дальше.
После команды серверу идет часть URI запроса относительно хоста. Например, в данном случае мы запрашиваем содержимое страницы index.php, которая находится в корневом каталоге хоста. Но мы также, можем запросить и такой URI: /info/price.php?type=1 и он будет прекрасно работать.
Далее, в первой строке запроса клиента следует указание вида протокола, в данном случае он указан как HTTP/1.1 (может быть и HTTP/1.0 и HTTP/0.9), но обычно используют HTTP/1.0.
В строке (Host:) указывается название хоста к которому мы отправляем http-запрос.
В строке (User-Agent:) указывается название клиента (в данном случае одна из версий браузера Mozilla).
В строке (Accept:) указываем в каком формате мы хотим получить данные.
В строке (Connection:) мы закрываем соединение. Это является правилом хорошего тона, так как сервер при обращении к нему создает отдельное соединение, которое обслуживает все дальнейшие Ваши запросы. Однако, если его не закрыть ничего не случится, сервер закроет его сам, но через определенный промежуток времени.
Пример PHP кода для запроса страницы через HTTP протокол:
Функция fsockopen имеет следующие параметры:
"master-web.com.ua" — название домена, к которому осуществляется подключение, можно, также, указать ip-адрес (например, "62.149.26.133");
80 — адрес порта удаленного сервера, к которому подключаемся;
$errno — в случае ошибки соединения в эту переменную заносится номер ошибки;
$errstr — в случае ошибки соединения в эту переменную заносится текстовое объяснение ошибки;
30 — время в миллисекундах на протяжении которого будут осуществляется попытки соединится или timeout по истечении которого попытки соединения будут прекращены.
Функция fwrite($fp, $query) — отправляет запрос $query и записывает ответ в файловый поток $fp.
Функция fgets($fp, 4096) — считывает построчно содержимое файловый поток $fp.
В результате удачного соединения (открытия сокета) переменная $fp обретает значение и мы отправляем текстовый запрос к серверу. Составить правильный текстовый запрос к серверу очень важно, поэтому я детально постараюсь его описать.
Запрос клиента может состоять из пары строк, а может и из десятка строк. Все зависит специфики запроса и того, что Вы сами хотите сообщить серверу. Каждая строка (кроме первой) состоит из параметра и его значения разделенные двоеточием :, например, Host: master-web.com.ua , Referer: http://google.com/ , Cookie: income=1 и т.д.
В конце строки в обязательном порядке должен быть код переноса строки " ". Часто пишут " ", где " " — перенос строки, а " " — перевод каретки в начало строки. Весь http-заголовок заканчивается двойным переносом строки, например Connection: Close или просто User-Agent: Mozilla/5.0 (compatible; MSIE 6.0; Windows 98) .
Спросите: зачем необходим двойной перенос строки? Во-первых, согласно спецификации HTTP, двойной перенос означает окончание http-запроса, а во-вторых, вспомните, что POST передача подразумевает передачу все данных не в строке запроса (в виде ..index.php?var1=1&var2=2), а внутри http-запроса:
Как двойной перенос строки " " отделяет http-запрос от переменных, так он и отделяет http-ответ сервера от содержимого страницы. Благодаря этому клиенты (браузера) выводят на экран страницу без заголовка ответа.
Перечень параметров, которые могут передаваться серверу:
Accept
Пример: Accept: text/html, text/plain, image/gif, image/jpeg
Эта строка используется клиентом, что сказать серверу, какие типы данных он воспринимает. На основе этого заголовка создается переменная окружения HTTP_ACCEPT_ENCODING.
Accept-Encoding
Пример: Accept-Encoding: bzip2, gzip
Определяет типы сжатия, с которыми может работать наш браузер/скрипт, и которые желательно использовать при передаче документа (если сервер поддерживает данные форматы сжатия).
Accept-Language
Пример: Accept-Language: ru,en-us;q=0.7,en;q=0.3
Означает, какая раскладка клавиатуры у нас установлена и на каком языке должен возвращаться запрошенный документ.
Accept-Charset
Пример: Accept-Charset: koi8-r;q=1.0, iso-8859-5;q=0.9, iso-8859-1;q=0.1
Определяет кодировки, с которыми может работать наш браузер/скрипт, и которые желательно использовать при передаче документа.
Cookie
Пример: Cookie: var1=1;var2=2;type=blob;
Передача cookie, на основе этого заголовка создается глобальный массив $_COOKIE.
Content-length
Пример: Content-length: 1001
Длина данных в байтах, переданных после двух переносов строки. Актуально при передачи данных методом POST или когда сервер отвечает на запрос. Размер переданных данных должен быть обязательно равен этому значению, иначе сервер ничего не будет выполнять, так как посчитает, что получил неполный пакет данных. На основе этого заголовка создается переменная окружения $ _SERVER["CONTENT_LENGTH"].
Content-Type
Пример: Content-Type: text/html;charset=ISO-8859-4
Тип данных, которые передаются в теле запроса. Поле Content-Type не имеет значения по умолчанию.
Keep-Alive
Пример: Keep-Alive: 300
Определяет время в секундах, в течение которого данное соединение с сервером должно удерживаться (не должно разрываться).
Referer
Пример: Referer: info-pages.com.ua
URL страницы, с которой клиент перешел на данную страницу. На основе этого параметра создается переменная окружения $_SERVER["HTTP_REFERER"].
User-Agent
Пример: User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Строка, описывающая браузер и ОС. На основе этого заголовка создается переменная окружения $_SERVER["HTTP_USER_AGENT"].
Теперь Вы можете полноценно обмениваться http-сообщениями с любым сервером, используя сокеты. При этом Вы можете послать ему любое значение одного из заголовков. Например, если Вы включаете в запрос http-заголовок "User-Agent: Opera/7.23 (Windows 98; U) [en]", то сервер будет думать что у Вас установлена Windows 98 и работаете Вы под Operо’й. А если вы укажите такой заголовок "Referer: google.com", то сервер решит, что Вы пришли из Гугл страницы.
в php.ini необходимо раскомментировать extension=php_sockets.dll, также проверьте с помощью функции phpinfo(); включенность сокетов в разделе sockets
Сетевые протоколы:
TCP — протокол управления передачей (Transmission Control Protocol).
TCP/IP — (Transmission Control Protocol/Internet Protocol) — набор сетевых протоколов, позволяющих компьютерам (различных аппаратных платформ и с разными операционными системами) взаимодействовать по соединенным сетям и через Интернет. Любой компьютер в Интернете поддерживает tcp/ip. Это базовый протокол, используемый Internet.
UDP — дополнительный компонент протокола tcp, поддерживающий выполняющуюся без подключений службу датаграмм, не гарантирующую ни доставку, ни правильную последовательность доставленных пакетов (аналогично протоколу ip).
FTP — один из протоколов tcp/ip, используемый для копирования файлов с одного компьютера на другой через Интернет. При этом оба компьютера должны поддерживать соответствующие роли ftp: один должен быть клиентом ftp, а другой — сервером ftp.
SSL — протокол, обеспечивающий защиту передаваемых данных с помощью шифров.
TLS — стандартный протокол, используемый для обеспечения безопасности веб коммуникаций в Интернете и интрасетях. Позволяет клиентам проверять подлинность серверов или (необязательно) серверам проверять подлинность клиентов. Также обеспечивает безопасный канал за счет шифрования соединений. Протокол tls является самой последней и более безопасной версией протокола ssl.
SMTP (Simple Mail Transfer Protocol) — что означает простой протокол передачи электронной почты;
POP (Post Office Protocol) — почтовый протокол для приема электронной почты.
В свою очередь в семействе TCP/IP существуют следующие протоколы:
HTTP — (Hypertext Transfer Protocol) протокол прикладного уровня передачи данных в первую очередь в виде текстовых сообщений. Основой http является технология «клиент-сервер», то есть клиенты посылают запрос, а серверы, которые ожидают соединения для получения запроса, производят необходимые действия и возвращают обратно сообщение с результатом. Порт сервера по умолчанию 80 или 8080.
HTTPS — расширение протокола http, поддерживающее шифрование. Https не является отдельным протоколом. По сути это обычный http, работающий через шифрованные транспортные механизмы ssl и tls. Порт сервера по умолчанию 443.
(PHP 4, PHP 5, PHP 7)
fsockopen — Открывает соединение с интернет сокетом или доменным сокетом Unix
Описание
Устанавливает соединение с сокетом ресурса hostname .
PHP поддерживает целевые ресурсы в интернете и Unix доменах в том виде, как они описаны в Список поддерживаемых транспортных протоколов. Список поддерживаемых транспортов можно получить с помощью функции stream_get_transports() .
По умолчанию, сокет будет открыт в блокирующем режиме. Переключить его в неблокирующих режим можно функцией stream_set_blocking() .
stream_socket_client() выполняет аналогичную функцию, но предоставляет более широкий выбор настроек соединения, включающий установку неблокирующего режима и возможность предоставления потокового контекста.
Список параметров
Если установлена поддержка OpenSSL, можно использовать SSL или TLS протоколы соединений поверх TCP/IP при подключении к удаленному хосту. Для этого перед hostname нужно добавить префикс ssl:// или tls://.
Номер порта. Его можно не указывать, передав -1 для тех протоколов, которые не используют порты, например unix://.
Если этот параметр предоставить, то в случае ошибки системного вызова функции connect() он будет принимать номер этой ошибки.
Если значение параметра errno равно 0, а функция вернула FALSE , значит ошибка произошла до вызова connect(). В большинстве случаев это свидетельствует о проблемах при инициализации сокета.
Сообщение об ошибке в виде строки.
Таймаут соединения в секундах.
Если требуется установить таймаут чтения/записи данных через сокет, используйте функцию stream_set_timeout() , так как параметр timeout функции fsockopen() ограничивает только время процесса установки соединения с сокетом.
Возвращаемые значения
fsockopen() возвращает файловый указатель, который можно передавать в функции работающие с файлами (такие как fgets() , fgetss() , fwrite() , fclose() и feof() ). Если вызов завершится неудачей, функция вернет FALSE .
Ошибки
Вызывает ошибку уровня E_WARNING , если hostname не является допустимым доменом.
Примеры
Пример #1 Пример использования fsockopen()
Пример #2 Использование UDP соединения
Пример ниже демонстрирует, как получить день и время от UDP службы "daytime" (порт 13) на вашей машине.
Примечания
В зависимости от окружения, Unix домен или таймаут установки подключения могут оказаться недоступными.
Иногда UDP сокеты получают статус открытых, даже если удаленный хост недоступен. Ошибка проявит себя только во время чтения или записи данных в/из этого сокета. Причиной этому служит тот факт, что протокол UDP передает данные без установки соединения. То есть операционная система не устанавливает и не держит соединение с сокетом, пока не начнется передача данных.
Замечание: При указании числового адреса IPv6 (например, fe80::1) вы должны заключать его в квадратные скобки. Например, tcp://[fe80::1]:80.
Смотрите также
- pfsockopen() — Открывает постоянное соединение с Интернет или сокетом Unix домена
- stream_socket_client() — Открывает соединение с интернет-сокетом или с доменным сокетом Unix
- stream_set_blocking() — Устанавливает блокирующий/неблокирующий режим на потоке
- stream_set_timeout() — Устанавливает значение тайм-аута на потоке
- fgets() — Читает строку из файла
- fgetss() — Прочитать строку из файла и отбросить HTML-теги
- fwrite() — Бинарно-безопасная запись в файл
- fclose() — Закрывает открытый дескриптор файла
- feof() — Проверяет, достигнут ли конец файла
- socket_connect() — Начинает соединение с сокетом
- Расширение Curl





