Анимация
JavaScript
|
Главная Библионтека К счастью, на CPAN имеются модули для всех протоколов. Большинство модулей реализует клиентскую, а не серверную сторону протокола. Следовательно, программа сможет использовать эти модули для отправки почты, по не для выполнения функций почтового сервера, к которому подключаются другие клиенты. Она может читать и отправлять новости, но не являться сервером новостей для других клиентов; обмениваться файлами с сервером FTP, но не быть сервером FTP; и т. д. Большинство этих модулей принадлежит иерархии Net;;. Модуль Net:;FTP используется для отправки и приема файлов по FTP; модуль Net::NNTP - для чтения и отправки новостей Usenet; модуль Net:;Telnet - для имитации подключения к другому компьютеру; модуль Net;:Whois - для получения данных об имени домена; модуль Net::Ping - для проверки связи с компьютером, а модули Net;;P0P3 и Mail:;Mailer - для отправки и получения почты. Протокол CGI рассматривается в главе 19 «Программирование CGb, а протокол HTTP - в главе 20 «Автоматизация в Web». Большинство этих модулей написал Грэхем Барр, автор модулей IO;;Socket, использовавшихся в низкоуровневых сетевых коммуникациях в главе 17 «Сокеты». Он нанисал Net::FTP, Net;;NNTP, Net;;P0P3 и Mail;:Mailer. Джей Роджерс (Jey Rogers) написал Net;:Telnet, а Чип Зальценберг (Chip Salrenberg) - Net::Whois. Благодаря им вам не придется заново изобретать велосипед! 18.1. Простой поиск в DNS Проблема Требуется определить IP-адрес хоста или преобразовать IP-адрес в имя. Сетевые серверы решают эту задачу в процессе аутентификации своих клиентов, а клиенты - когда пользователь вводит имя хоста, но для библиотеки сокетов Perl нужен IP-адрес. Более того, многие серверы регистрируют в файлах журналов IP-адреса, но аналитическим программам и людям удобнее работать с именами хостов. Решение Для получения всех IP-адресов по имени хоста (например, www.perl.com) воспользуйтесь фунгсцией gethostbyname; use Socket; ©addresses = gethostbyname($name) or die Cant resolve Sname; S\n"; ©addresses = map { inet ntoa($ ) } @addresses[4 .. $#addresses], # ©addresses - список IP-адресов ("208.201 239 48", "208,201.239.48") Если вам нужен только первый адрес, воспользуйтесь функцией inet aton: use Socket; Saddress = inet ntoa(inet aton(Sname)); tt Saddress - один IP-адрес ("208.201.239 48") 18.1. Простой поиск в DNS 645 Для получения имени хоста по строке с IP-адресом (например," 208.201.239.48"), воспользуйтесь следующим фрагментом: use Socket; $name = gethostbyaclclr(inet aton($address), AF INET) or die "Cant resolve $address; $!\n": tt $name - имя хоста ("www. perl.com") Комментарий Наща задача усложняется тем, что функции Perl являются простыми оболочками для системных функций С, поэтому IP-адреса приходится преобразовывать из ASCII-строк ("208. 201. 239.48") в структуры С. Стандартный модуль Socket содержит функцию inet aton для перехода от ASCII к упакованному числовому формату и функцию inet ntoa, выполняющую обратное преобразование: use Socket; $packed address = inet aton("208.146 140 1"); $ascii address = inet ntoa($packed address); Функция gethostbyname получает строку, содержащую имя хоста (или IP-адрес). В скалярном контексте она возвращает IP-адрес удаленного хоста, который можно передать inet ntoa (или undef в случае ошибки). В списковом контексте она возвращает список, состоящий по крайней мере из пяти элементов (или пустой список в случае ошибки). Список состоит из следующих элементов. Индекс Значение 0 Официальное имя хоста 1 Синонимы (строка, разделенная пробелами) 2 Тип адреса (обычно AF INET) 3 Длина структуры адреса (не имеет значения) 4,5... Структуры адресов Имени хоста может соответствовать несколько IP-адресов; в частности, это происходит на сильно загруженных Web-серверах, где для снижения загрузки на разных компьютерах размещаются идентичные Web-страницы. В подобных ситуациях сервер DNS, предоставляющий адреса, чередует их, обеспечивая сбалансированную нагрузку на сервер. Если вы хотите выбрать IP-адрес для подключения, просто возьмите первый адрес в списке (а если он не работает, попробуйте остальные адреса): Spacked = gethostbyname($hostname) or die "Couldnt resolve address for Shostname; $!\n"; Saddress = inet ntoa($packed); print "I will use Saddress as the address for $hostname\n"; Используя имена хостов для разрешения или отказа в обслуживании, будьте осторожны. Любой желающий может настроить свой сервер DNS так, чтобы его компьютер идентифицировался как www.whitehouse.gov, www.yahoo.com или this.is.not.funny. Нельзя сказать, действительно ли ему принадлежит то имя, на которое он претендует, пока вы не вызовете gethostbyname и не проверите исходный адрес по адресному списку для данного имени. # Saddress - проверяемый IP-адрес (например, "128.138.243.20") use Socket; Sname = gethostbyaddr(inet aton($address), AF INET) or die "Cant look up Saddress : $i\n"; @addr = gethostbyname($name) or die "Cant look up Sname . S\n"; Sfound = grep { Saddress eq inet ntoa(S ) } @addr[4..S#addr], Оказывается, даже такой алгоритм не дает полной уверенности в полученном имени, поскольку существуют разнообразные обходные пути. Даже IP-адрес, из которого вроде бы поступают пакеты, может быть поддельным, и в процессе аутентификации не следует полагаться на сетевой уровень. В действительно важных ситуациях всегда выполняйте аутентификацию сами (с помощью паролей или криптографических методов), поскольку сеть IPv4 не проектировалась для соблюдения безопасности. Информация о хосте не ограничивается адресами и синонимами. Чтобы полноценно работать с дополнительными данными, воспользуйтесь модулем Net:;DNS с CPAN. Программа 18.1 показывает, как получить записи MX (mail exchange) для произвольного хоста. Пример 18.1. mxhost #i/usr/bin/perl # mxhost - поиск записей mx для хоста use Net.-DNS; Shost = shift, Sres = Net-;DNS;;Resolver->new(); @mx = mx(Sres, Shost) or die "Cant find MX records for Shost (".$res->errorstring,")\n"; foreach Srecord (@mx) { print Srecord->preference, " ", $record->exchange, "\n"; Примерный вывод выглядит так; % mxhost cnn.com 10 mall.turner.com 30 alfw2.turner.com Функция inet aton, как и gethostbyname, получает строку с именем хоста или IP-адресом, однако она возвращает только первый IP-адрес для данного хоста. Чтобы узнать все IP-адреса, приходится писать дополнительный код. Модуль Net::hostent поддерживает соответствующие средства доступа по имени. Пример 18.2 показывает, как это делается. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 [ 209 ] 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |