В этой статье рассматривается использование сетевых функций популярного языка программирования php. При написании этой статьи я решил отойти от общепринятой схемы, которая употребляется в руководстве по php: <тип название (параметры) - описание> Наоборот, в статье собраны полезные практические примеры. Из-за большого объема информации (язык php предназначен для web-программирования, поэтому достаточно большую часть функций можно назвать сетевыми), я ограничусь только теми, которые использую наиболее часто. Переменные окружения интерфейса cgi Получение документа по протоколу http Работа с сокетами Функции для работы с dns Функции протоколирования Отправка сообщения Переменные окружения интерфейса cgi При использовании интерфейса cgi (common gateway interface) программисту доступно множество переменных окружения. Сейчас мы рассмотрим наиболее полезные в нашем случае переменные (см. таблицу 1). Переменные окружения можно использовать в программе также как обыкновенные переменные. Например, для вывода ip-адреса клиента достаточно одного оператора: echo $remote_addr Таблица 1. Переменная Описание http_user_agent С помощью этой переменой можно определить броузер пользователя, а также его операционную систему. Например, для netscape, запущенным под linux, эта переменная будет содердать значение: mozilla/4.7 [en] (linux; i) Для internet explorer 5.0 и win98: mozilla/4.0 (compatible; msie 5.0; windows 98; digext) http_host Содержит доменное имя сервера, на котором запущен сценарий. server_port Порт сервера, к которому обратился броузер. Обычно используется порт 80. remote_addr Содержит ip-адрес клиента, то есть ip-адрес пользователя, который запустил броузер remote_port Порт для получения ответа сервера. Этот порт закрепляется за каждой запущенной копией броузера Получение документа по протоколу http Получить документ по протоколу http довольно просто: Листинг 1. Получение документа по http <? 1. $file = join( '', file( 'http://localhost/index.html' ) ); 2. echo $file; ?> В первой строке листинга 1 мы получаем весь документ в строку $file, а второй - отправляем документ в броузер. Функция file() возвращает массив строк. n-ый элемент этого массива соответствует n-ой строке файла. Если нас интересует html-код получаемого документа, вывести код в броузер поможет листинг 2, который я позаимствовал из руководства по php. Листинг 2. Вывод html-кода документа <? 1. $fcontents = file( 'http://localhost' ); 2. while ( list( $line_num, $line ) = each( $fcontents ) ) { 3. echo "<b>line $line_num:</b> " . htmlspecialchars( $line) . "<br> \n"; 4. } ?> Работа с сокетами Функция file() (равно как и fopen() ) позволяет нам работать только с содержимым файла, который получен по тому или иному протоколу. Предположим, что нас интересуют заголовки, переданные сервером. Получить эти заголовки мы можем с помощью функции int fsockopen(string $host, int $port, [, int &$errno] [, string &$errstr]) Данная функция позволяет инициализировать потоковое соединение с указанным хостом и программой, которая связана с указанным портом. Кроме того, эта функция поддерживает unix-сокеты. При этом параметр $hostname будет использован как путь к файлу сокета, а параметр $port должен быть равен 0. После установления соединения функция возвращает обыкновенный дескриптор файла. С этим дескриптором могут работать функции fread(), fwrite(), fgets(), feof() и другие. В случае ошибки функция возвратит false и, если указаны необязательные параметры $errno и $errstr, соответственно, номер ошибки и текст сообщения об ошибке. Рассмотрим листинг 3 - <Виртуальный браузер>: мы посылаем серверу http-запрос get и, получив ответ, выводим его в броузер. Листинг 3. <Виртуальный браузер> <? // Подключаемся к серверу 1. $fsoc = fsockopen("localhost",80); 2. fputs($fsoc, "get / http/1.0\n\n"); 3. echo ""; 4. while (!feof($fsoc)) 5. echo htmlspecialchars(fgets($fsoc,1000)); 6. echo ""; // Отключаемся от сервера 7. fclose($fsoc); ?> Как я уже отмечал выше, при использовании функции fsockopen мы получаем весь ответ сервера - вместе с заголовками. Функцию htmlspesialchars() мы используем для корректного отображения html-кода в текстовом формате. В броузере мы должны получить примерно следующее: http/1.1 200 ok date: sat, 16 mar 2002 10:46:59 gmt server: apache/1.3.12 (linux) last-modified: sat, 20 nov 1999 13:29:40 gmt etag: "0-574-3836a244" accept-ranges: bytes content-length: 1396 connection: close content-type: text/html <!doctype html public "-//w3c//dtd html 3.2 final//en"> <html> sp;<head> <title>test page for apache installation</title> </head> ... Ответ сервера http/1.1 200 ok соответствует коду ответа 200 и означает безошибочное выполнение операции (в данном случае передачи документа по запросу get). Установить нужный нам заголовок ответа мы можем с помощью функции header(). Например, header("location://www.softerra.ru/freeos"); Запретить кэширование можно с помощью установки заголовка pragma: no-cache. К сожалению одного этого заголовка явно не хватит для запрещения кэширования. Для полного запрета нужно использовать целых четыре заголовка. Установить с помощью header их можно так: header("pragma: no-cache"); header("cache-control: no-cache, must-revalidate"); header("expires: mon, 01 jan 1990 01:01:01 gmt"); header("last-modified: ".gmdate("d, d m y h:i:s")."gmt"); Первый из них устанавливает заголовок запрета кэширования согласно протокола http/1.0, а второй - http/1.1. Третий определяет задает дату в прошлом, а четвертый устанавливает дату последнего обновления документа. Функция gmdate() возвращает дату в нужном нам формате. Устанавливать все четыре заголовка крайне желательно, так как запрет кэширования может не сработать или на прокси-сервере или в броузере, и пользователь получит устаревшую версию документа. Функции для работы с dns При написании сценариев вне зависимости от языка программирования часто возникает потребность разрешения ip-адреса в доменное имя и наоборот. Преобразование ip-адреса в доменное имя выполняет функция string gethostbyaddr(string $ip_address); В случае ошибки возвращается ip-адрес. Преобразование имени хоста в ip-адрес выполняет функция string gethostbyname(string $host); Если вам нужно получить все ip-адреса хоста с именем $host, используйте функцию array gethostbynamel(string $host); В листинге 4 применена именно функция gethostbynamel. Листинг 4. Получение всех ip-адресов хоста $host <? $host="www.yahoo.com"; $ips=gethostbynamel($host); foreach($ips as $ip) echo $ip; ?> Определить почтовик для указанного хоста hostname можно с помощью функции int getmxrr(string hostname, array mxhosts, array [weight]); Данная функция запрашивает dns на предмет наличия записей mx для указанного хоста. Следующие функции никакого отношения к dns не имеют, но чтобы не создавать другого раздела в статье, я описал их здесь. int getprotobyname(string name); Функция getprotobyname() возвращает номер протокола, который соответствует имени $name. Обратная ей функция string getprotobynumber(int number); возвращает имя протокола по его номеру. Функция int getservbyname(string service, string protocol); возвращает номер порта internet-сервиса, название которого указано в параметре $service. Второй параметр функции - это протокол: tcp или udp. Например, оператор echo getservbyname("ftp", "tcp"); выведет в окно броузера число 21. Для функции getservbyname() также существует обратная ей: string getservbyport(int port, string protocol); При использовании функции getservbyport() нужно указать номер порта и протокол (tcp или udp) и, как результат, вы получите название internet-сервиса. Например, echo getservbyport(21, "tcp"); выведет в окно броузера название сервиса - ftp. Функции протоколирования Иногда нужно записать некоторую информацию, например, сообщение об ошибке, в системный журнал syslog. В php для этого предусмотрена целая серия функций: int openlog(string ident, int option, int facility); int syslog(int priority, string message); int closelog(void); Первая из них открывает соединение с демоном syslog. Вторая - порождает системное сообщение (другими словами записывает сообщение с указанным приоритетом в протокол). Функция closelog() закрывает соединение протокола. О применении демона syslog вы можете прочитать в статье Станислава Лапшанского Демон следит за системой Отправка сообщения Я не открою Америки, если заявлю, что для отправления почты в php используется функция mail. Здесь я только приведу несколько рекомендаций относительно использования этой функции. Напомню формат вызова функции: mail(string $to, string $subject, string $msg [, string $headers]); Например, mail("root@localhost", "test", "message\nline2", "from: den@localhost\n", "reply-to: den@localhost\n"); Все работает хорошо до тех пор, пока не начинаются проблемы с кодировками. Для указания кодировки нужно установить заголовок content-type: text/plain; charset=koi8-r Для преобразования самих кодировок используется функция convert_cyr_string(). Использовать ее предельно просто, например, convert_cyr_string($msg,"k","w"); Этим вызовом функции convert_cyr_string() мы преобразуем кодировку koi8-r в windows-1251. Разумеется, заголовок content-type нужно изменить на content-type: text/plain; charset=win-1251 При использовании функции mail целесообразно хранить все заголовки в теле письма. Тогда один раз вызвав функции convert_cyr_string() мы конвертируем все письмо в нужныю нам кодировку. В этом случае вызов функции mail должен быть произведен так: mail("root@localhost","",$msg); Значение переменной $msg будет таким: $msg="from: Денис <den@localhost>\n to: Администратор <root@localhost>\n content-type: text/plain; charset=win-1251\n \n Текст сообщения ... Обратите внимание, что после всех заголовков должно следовать два символа новой строки \n: один после последнего заголовка, а другой перед текстом сообщения.
|