В этой статье рассматривается использование сетевых функций популярного
языка программирования PHP. При написании этой статьи я решил отойти от
общепринятой схемы, которая употребляется в руководстве по PHP:
Обзор сетевых функций PHP
Денис Колисниченко
"тип название (параметры) - описание"
Наоборот, в статье собраны полезные практические примеры. Из-за большого
объема информации (язык PHP предназначен для Web-программирования, поэтому
достаточно большую часть функций можно назвать сетевыми), я ограничусь
только теми, которые использую наиболее часто.
Переменные окружения интерфейса CGI Получение документа по протоколу HTTP Работа с сокетами Функции для работы с DNS Функции протоколирования Отправка сообщения
При использовании интерфейса 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 довольно просто:
Листинг 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. } ?>
Листинг 3. "Виртуальный броузер"
<? // Подключаемся к серверу 1. $fsoc = fsockopen("localhost",80); 2. fputs($fsoc, "GET / HTTP/1.0\n\n"); 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 их можно так:
Первый из них устанавливает заголовок запрета кэширования согласно протокола HTTP/1.0, а воторой - HTTP/1.1. Третий определяет задает дату в прошлом, а четвертый устанавливает дату последнего обновления документа. Функция gmdate() возвращает дату в нужном нам формате. Устанавливать все четыре заголовка крайне желательно, так как запрет кэширования может не сработать или на прокси-сервере или в броузере, и пользователь получит устаревшую версию документа.
При написании сценариев вне зависимости от языка программирования часто возникает потребность разрешения 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 для этого предусмотрена целая
серия функций:
Первая из них открывает соединение с демоном syslog. Вторая - порождает
системное сообщение (другими словами записывает сообщение с указанным приоритетом
в протокол). Функция closelog() закрывает соединение протокола.
О применении демона syslog вы можете прочитать в статье Станислава Лапшанского "
Демон следит за системой" - http://www.softerra.ru/freeos/15618/page1.html
Я не открою Америки, если заявлю, что для отправления почты в 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: один после последнего заголовка, а другой перед текстом сообщения. На этом я и заканчиваю этот небольшой обзор, любые ваши комментарии, вопросы прошу присылать по адресу dhsilabs@mail.ru