Огляд мережних функцій PHP  h2>
 В
цій статті розглядається використання мережевих функцій популярної мови
програмування PHP. При написанні цієї статті я вирішив відійти від загальноприйнятої
схеми, яка вживається в керівництві по PHP:  p>
 «тип
назва (параметри) - опис » p>
 Навпаки,
у статті зібрані корисні практичні приклади. З-за великого обсягу
інформації (мова PHP призначений для Web-програмування, тому досить
більшу частину функцій можна назвати мережевими), я обмежусь тільки тими,
які використовую найчастіше.  p>
 Змінні оточення інтерфейсу
CGI  b>  p>
 При
використанні інтерфейсу CGI (Common Gateway Interface) програмісту є
безліч змінних оточення. Зараз ми розглянемо найбільш корисні в нашому
випадку змінні (див. таблицю 1).  p>
 Змінні
оточення можна використовувати в програмі також як звичайні змінні.
Наприклад, для виведення IP-адреси клієнта достатньо одного оператора:  p>
 echo
$ REMOTE_ADDR  p>
 Таблиця
1.  p>
 
  
  
 Змінна  p>
  
  
  
 Опис  p>
  
 
 
  
  
 HTTP_USER_AGENT  p>
  
  
  
 За допомогою цієї зміною можна
  визначити броузер користувача, а також його операційну систему. Наприклад,
  для Netscape, запущеним під Linux, ця змінна буде содердать значення:  p>
  
 Mozilla/4.7 [en] (Linux; I)  p>
  
 Для Internet Explorer 5.0 і Win98:  p>
  
 Mozilla/4.0 (compatible; MSIE 5.0; Windows
  98; DigExt)  p>
  
 
 
  
  
 HTTP_HOST  p>
  
  
  
 Містить доменне ім'я сервера,
  на якому запущений сценарій.  p>
  
 
 
  
  
 SERVER_PORT  p>
  
  
  
 Порт сервера, до якого
  звернувся броузер. Зазвичай використовується порт 80.  P>
  
 
 
  
  
 REMOTE_ADDR  p>
  
  
  
 Містить IP-адреса клієнта, то
  є IP-адресу користувача, який запустив броузер  p>
  
 
 
  
  
 REMOTE_PORT  p>
  
  
  
 Порт для отримання відповіді
  сервера. Цей порт закріплюється за кожною запущеної копією броузера  p>
  
 
Отримання документа по протоколу HTTP  p>
 Отримати
документ по протоколу HTTP досить просто:  p>
 Лістинг
1. Отримання документа по HTTP  p>
   p>
 1. $ file = join ('', file (
'http://localhost/index.html'));  p>
 2.
echo $ file;  p>
?>  p>
 В
першому рядку лістингу 1 ми одержуємо весь документ в рядок $ file, а другий --
відправляємо документ в броузер. Функція file () повертає масив рядків. N-ий
елемент цього масиву відповідає N-ої рядку файлу.  p>
 Якщо
нас цікавить HTML-код одержуваного документа, вивести код в броузер допоможе
лістинг 2, який я запозичив з керівництва по PHP.  p>
 Лістинг
2. Висновок HTML-коду документа  p>
   p>
 1. $ fcontents = file (
'http://localhost');  p>
 2. while (list ($ line_num, $ line)
= Each ($ fcontents)) ( p>
 3. echo " Line
$ line_num:  b> ". htmlspecialchars ($ line)." 
 n ";  p>
 4.
)  p>
?>  p>
 Робота з сокетами  b>  p>
 Функція
file () (так само як і fopen ()) дозволяє нам працювати тільки з вмістом файла,
який отриманий з того чи іншого протоколу. Припустимо, що нас цікавлять
заголовки, передані сервером. Отримати ці заголовки ми можемо за допомогою функції
 p>
 int fsockopen (string $ host, int
$ port, [, int & $ errno] [, string & $ errstr])  p>
 Дана
функція дозволяє ініціалізувати потокове з'єднання з зазначеним хостом і
програмою, яка пов'язана із зазначеним портом. Крім того, ця функція
підтримує Unix-сокети. При цьому параметр $ hostname буде використаний як
шлях до файлу сокета, а параметр $ port повинен бути дорівнює 0.  p>
 Після
підтримання зв'язку функція повертає звичайний дескриптор файлу. З
цим дескриптором можуть працювати функції fread (), fwrite (), fgets (), feof () і
інші.  p>
 В
випадку помилки функція поверне false і, якщо вказані необов'язкові параметри
$ errno і $ errstr, відповідно, номер помилки і текст повідомлення про помилку.  p>
 Розглянемо
лістинг 3 - «Віртуальний браузер»: ми посилаємо серверу HTTP-запит GET і,
одержавши відповідь, виводимо його в броузер.  p>
 Лістинг
3. «Віртуальний браузер»  p>
   p>
//
Підключаємося до сервера  p>
 1. $ fsoc =
fsockopen ( "localhost", 80);  p>
 2. fputs ($ fsoc, "GET /
HTTP/1.0nn "); p>
 3. echo "
";  p>
 4. while (! feof ($ fsoc))  p>
 5. echo
HtmlSpecialChars (fgets ($ fsoc, 1000 )); p>
 6. echo " pre >"; p>
//
Відключається від сервера  p>
 7.
fclose ($ fsoc);  p>
?>  p>
 Як
я вже зазначав вище, при використанні функції fsockopen ми отримуємо вся відповідь
сервера - разом із заголовками. Функцію HtmlSpesialChars () ми використовуємо для
коректного відображення HTML-коду в текстовому форматі. У броузері ми повинні
отримати приблизно наступне:  p>
 HTTP/1.1
200 OK  p>
 Date:
Sat, 16 Mar 2002 10:46:59 GMT  p>
 Server: Apache/1.3.12 (Linux)  p>
 Last-Modified: Sat, 20 Nov 1999
13:29:40 GMT  p>
 ETag: "0-574-3836a244"  p>
 Accept-Ranges: bytes  p>
 Content-Length: 1396  p>
 Connection: close  p>
 Content-Type: text/html  p>
   p>
   p>
 sp; 
  p>
 
 Test Page for Apache
Installation  TITLE>  p>
  HEAD>  p>
 ... p>
 Відповідь
сервера HTTP/1.1 200 OK відповідає коду відповіді 200 і означає безпомилкове
виконання операції (в даному випадку передачі документа на запит GET).  p>
 Встановити
потрібний нам заголовок відповіді ми можемо з допомогою функції Header (). Наприклад,
Header ( "Location:// www.softerra.ru/freeos");  p>
 Заборонити
кешування можна за допомогою установки заголовка Pragma: no-cache. На жаль
одного цього заголовка явно не вистачить для заборони кешування. Для повного
заборони потрібно використовувати цілих чотири заголовка. Встановити за допомогою Header їх можна так:  p>
 Header ( "Pragma:
no-cache ");  p>
 Header ( "Cache-control:
no-cache, must-revalidate ");  p>
 Header ( "Expires: Mon, 01 Jan
1990 01:01:01 GMT ");  p>
 Header ( "Last-Modified:
". gmdate (" D, d M Y H: i: s ")." GMT ");  p>
 Перший
з них встановлює заголовок заборони кешування згідно протоколу HTTP/1.0,
а другий - HTTP/1.1. Третій визначає задає дату в минулому, а четвертий
встановлює дату останнього оновлення документа. Функція gmdate () повертає
дату в потрібному нам форматі. Встановлювати всі чотири заголовка вкрай
бажано, так як заборона кешування може не спрацювати або на проксі-сервер
або в броузері, і користувач отримає застарілу версію документа.  p>
 Функції для роботи з DNS  b>  p>
 При
написанні сценаріїв незалежно від мови програмування часто виникає
потреба дозволу IP-адреса в доменне ім'я і навпаки.  p>
 Перетворення
IP-адреса в доменне ім'я виконує функція  p>
 string gethostbyaddr (string
$ ip_address);  p>
 В
випадку помилки повертається IP-адресу.  p>
 Перетворення
імені хоста в IP-адреса виконує функція  p>
 string
gethostbyname (string $ host);  p>
 Якщо
вам потрібно отримати всі IP-адреси хоста з іменем "$ host, використовуйте функцію  p>
 array
gethostbynamel (string $ host);  p>
 В
лістингу 4 застосована саме функція gethostbynamel.  p>
 Лістинг
4. Отримання всіх IP-адрес хоста $ host  p>
   p>
 $ host = "www.yahoo.com";  p>
 $ ips = gethostbynamel ($ host);  p>
 foreach ($ ips as $ ip) echo $ ip;  p>
?>  p>
 Визначити
почтовик для зазначеного хоста hostname можна за допомогою функції  p>
 int getmxrr (string hostname, array
mxhosts, array [weight]);  p>
 Дана
функція запитує DNS на предмет наявності записів MX для зазначеного хоста.  p>
 Наступні
функції ніякого відношення до DNS не мають, але щоб не створювати іншого
розділу в статті, я описав їх тут.  p>
 int
getprotobyname (string name);  p>
 Функція
getprotobyname () повертає номер протоколу, який відповідає імені $ name.
 p>
 Зворотній їй
функція  p>
 string getprotobynumber (int number);
 p>
 повертає
ім'я протоколу за його номером.  p>
 Функція  p>
 int getservbyname (string service,
string protocol);  p>
 повертає
номер порту Internet-сервісу, назва якого зазначено в параметрі $ service.
Другий параметр функції - це протокол: tcp чи udp.  p>
 Наприклад,
оператор  p>
 echo
getservbyname ( "ftp", "tcp");  p>
 виведе
у вікно броузера число 21.  p>
 Для
функції getservbyname () також існує зворотна їй:  p>
 string getservbyport (int port,
string protocol);  p>
 При
використанні функції getservbyport () потрібно вказати номер порту і протокол (tcp
або udp) і, як результат, ви отримаєте назву Internet-сервісу.  p>
 Наприклад,
 p>
 echo
getservbyport (21, "tcp");  p>
 виведе
у вікно броузера назва сервісу - ftp.  p>
Опції протоколювання  p>
 Іноді
потрібно записати деяку інформацію, наприклад, повідомлення про помилку, в системний
журнал syslog. У PHP для цього передбачена ціла серія функцій:  p>
 int openlog (string ident, int
option, int facility);  p>
 int syslog (int priority, string
message);  p>
 int
closelog (void);  p>
 Перша
з них відкриває з'єднання з демоном syslog. Друга - породжує системне
повідомлення (іншими словами записує повідомлення з вказаним пріоритетом у
протокол). Функція closelog () закриває з'єднання протоколу.  p>
 Відправлення повідомлення  b>  p>
 Я
не відкрию Америки, якщо заявлю, що для відправки пошти в PHP використовується
функція mail. Тут я тільки наведу кілька рекомендацій щодо
використання цієї функції.  p>
 Нагадаю формат виклику функції:  p>
 mail (string $ to, string $ subject,
string $ msg [, string $ headers]);  p>
 Наприклад,  p>
 mail ( "root @ localhost",
"Test", "MessagenLine2", "From:
den @ localhostn "," Reply-To: den @ localhostn ");  p>
 Всі
працює добре до тих пір, поки не починаються проблеми з кодуваннями. Для
вказівки кодування потрібно встановити заголовок  p>
 Content-type:
text/plain; charset = koi8-r  p>
 Для
перетворення самих кодувань використовується функція convert_cyr_string ().
Використовувати її гранично просто, наприклад,  p>
 convert_cyr_string ($ msg, "k", "w");
 p>
 Цим
викликом функції convert_cyr_string () ми перетворимо кодування koi8-r в
windows-1251. Зрозуміло, заголовок Content-type потрібно змінити на  p>
 Content-type: text/plain;
charset = win-1251  p>
 При
використанні функції mail доцільно зберігати всі заголовки в тексті листа.
Тоді один раз викликавши функції convert_cyr_string () ми конвертуємо все листа до
нужнию нам кодування. У цьому випадку виклик функції mail повинен бути зроблений
так:  p>
 mail ( "root @ localhost ","",$ msg);
 p>
 Значення
змінної $ msg буде таким:  p>
 $ msg = "From: Денис  n  p>
 To: Адміністратор  n  p>
 Content-type: text/plain;
charset = win-1251n  p>
 n  p>
 Текст
повідомлення  p>
 ... p>
 Зверніть
увагу, що після всіх заголовків має слідувати два символи нового рядка
n: одна після останнього заголовка, а інший перед текстом повідомлення.  p>
 Список літератури  h2>
 Для
підготовки даної роботи були використані матеріали з сайту http://www.i2n.ru
 p>