div.main {margin-left: 20pt; margin-right: 20pt}
Обзор сетевых функций PHP Автор: Денис Колисниченко, dhsilabs@mail.ru Опубликовано:
21.03.2002 Оригинал: http://www.softerra.ru/review/program/16851/
В этой статье рассматривается использование
сетевых функций популярного языка программирования PHP. При написании этой
статьи я решил отойти от общепринятой схемы, которая употребляется в руководстве
по PHP: «тип название (параметры) – описание» Наоборот, в статье
собраны полезные практические примеры. Из-за большого объема информации (язык
PHP предназначен для Web-программирования, поэтому достаточно большую
часть функций можно назвать сетевыми), я ограничусь только теми, которые
использую наиболее часто.
Переменные окружения интерфейса 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.0nn");
3. echo "<pre>";
4. while (!feof($fsoc))
5. echo HtmlSpecialChars(fgets($fsoc,1000));
6. echo "</pre>";
// Отключаемся от сервера
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",
"MessagenLine2", "From: den@localhostn", "Reply-To: den@localhostn");
Все работает хорошо до тех пор, пока не
начинаются проблемы с кодировками. Для указания кодировки нужно установить
заголовок 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-1251n
n
Текст сообщения
...
Обратите внимание, что после всех заголовков
должно следовать два символа новой строки n: один после последнего заголовка, а
другой перед текстом сообщения. На этом я и заканчиваю этот небольшой обзор,
любые ваши комментарии, вопросы прошу присылать mailto:dhsilabs@mail.ru
|