Анимация
JavaScript
|
Главная Библионтека 17.7. Идентификация другого конца сокета Проблема Имеется сокет. Вы хотите идентифицировать компьютер, находящийся на другом конце. Решение Если вас интересует только IP-адрес удаленного компьютера, поступите следующим образом: use Socket, Sother end = getpeername(SOCKET) or die Couldn t identify other end S\n , (Sport Siaddr) = unpack sockaddr in(Sother end), Sip address = inet ntoa(Siaddr), Имя хоста определяется несколько иначе: use Socket, $other end = getpeernaffle(SOCKET) or die Couldn t identify other end S\n , (Sport, Siaddr) = unpack sockaddr in(Sother end), Sactual ip = inet ntoa(Siaddr), $claimed hostnaffle = gethostbyaddr(Siaddr, AF INET), @пате 1оокир = gethostbyname(Sclaimed hostname) or die Could not look up Sclaimed hostname $\n , @resolved ips = map { inet ntoa($ ) ) @name lookup[ 4 S#ips for hostname ] Комментарий В течение долгого времени задача идентификации подключившихся компьютеров считалась более простой, чем на самом деле. Функция getpeername возвращает IP-адрес удаленного компьютера в упакованной двоичной структуре (или undef в случае ошибки). Распаковка выполняется функцией inet ntoa. Если вас интересует имя удаленного компьютера, достаточно вызвать gethostbyadd г и поискать его в таблицах DNS, не так ли? Не совсем. Это лишь половина решения. Поскольку поиск по имени выполняется на сервере DNS владельца имени, а поиск по IP-адресу - на сервере DNS владельца адреса, приходится учитывать возможность, что компьютер, к которому вы подключились, выдает неверные имена. Например, компьютер evil.crackers.org может принадлежать злобным киберпиратам, которые сказали своему серверу DNS, что их IP-адрес (1.2.3.4) следует идентифицировать как trusted.dod.gov. Если ваша профамма доверяет trusted.dod.gov, то при подключении с evil.crackers.org функция getpeername вернет правильный IP-адрес (1.2.3.4), однако gethostbyadd г вернет ложное имя. 17.8. Определение вашего имени и адреса 621 Чтобы справиться с этой проблемой, мы берем имя (возможно, ложное), полученное от gethostbyaddr, и снова вызываем для него функцию gethostbyname. В примере с evil.crackers.org поиск для trusted.dod.gov будет выполняться на сервере DNS dod.gov и вернет настоящий IP-адрес (адреса) trusted.dod.gov Поскольку многие компьютеры имеют несколько IP-адресов (очевидный пример - распределенные Web-серверы), мы не можем использовать упрощенную форму gethostbyname; $packecl ip = gethostbyname($name) or die Couldn t look up Sname S\n , Sip.address = inet ntoa(Spacked ip), До настоящего момента предполагалось, что мы рассматриваем приложение с сокетами Интернета. Функцию getpeername также можно вызвать для сокета UNIX. Если на другом конце была вызвана функция bind, вы получите имя файла, к которому была выполнена привязка. Однако если на другом конце функция bind не вызывалась, то getpeername может вернуть пустую (неупакованную) строку, упакованную строку со случайным мусором, или undef как признак ощибки.., или ващ компьютер перезагрузится (варианты перечислены по убыванию вероятности и возрастанию неприятностей). В нащем компьютерном деле это называется «непредсказуемым поведениел!». Но даже этого уровня паранойи и перестраховки недостаточно. При желании можно обмануть сервер DNS, не находящийся в ващем непосредственном распоряжении, поэтому при идентификации и аутентификации не следует полагаться на имена хостов. Настоящие параноики и мизантропы обеспечивают безопасность с помощью криптографических методов. 1> Смотри также- Описание функций gethostbyaddr, gethostbyname и getpeername в perlfunc(l); описание функции inet ntoa в стандартном модуле Socket; документация по стандартным модулям lO..Socket и Net::hostnet. 17.8. Определение вашего имени и адреса Проблема Требуется узнать ваще (полное) имя хоста. Решение Сначала получите свое (возможно, полное) имя хоста. Воспользуйтесь либо стандартным модулем Sys;;Hostname: use Sys Hostname, Shostname = hostname(), либо функцией uname модуля POSIX; use POSIX qw(uname). (Skernel Shostname, Srelease, $version, Shardware) = unameO, Shostname = (ипате)[1], Затем превратите его в IP-адрес и преобразуйте в каноническую форму: use Socket, # Для AF INET Saddress = gethostbynameCShostname) or die Couldn t resolve Shostname S , Shostname = gethostbyaddr(Saddress, AF INET) or die Couldn t re-resolve Shostname $ Комментарий Для улучшения переносимости модуль Sys::Hostname выбирает оптимальный способ определения имени хоста, руководствуясь сведениями о вашей системе. Он пытается получить имя хоста несколькими различными способами, но часть из них связана с запуском других программ. Это может привести к появлению меченых данных (см. рецепт 19.1). С другой стороны, POSIX uname работает только в POSIX-системах и не гарантирует получения полезных данных в интересующем нас поле nodename. Впрочем, на многих компьютерах это значение все же приносит пользу и не страдает от проблем меченых данных в отличие от Sys::Hostname. Однако после получения имени хоста следует учесть возможность того, что в нем отсутствует имя домена. Например, Sys::Hostname вместо guanaco.camelids.org может вернуть просто guanaco. Чтобы исправить ситуацию, преобразуйте имя в IP-адрес функцией gethostbyname, а затем - снова в имя функцией gethostbyadd г. Привлечение DNS гарантирует получение полного имени. t> Смотри также- Описание функций gethostbyaddr и gethostbyname вperlfunc{\); документация по стандартным модулям Net::hostnet и Sys::Hostname. 17.9. Закрытие сокета после разветвления Проблема Ваша программа разветвилась, и теперь другому концу необходимо сообщить о завершении отправки данных. Вы попытались вызвать close для сокета, но удаленный конец не получает ни EOF, ни SIGPIPE. Решение Воспользуйтесь функцией shutdown: shutdown(SOCKET, 0), # Прекращается чтение данных shutdQwn(SOCKET, 1), tt Прекращается запись данных shutdown(SOCKET, 2), t( Прекращается работа с сокетом Используя объект IO::Socket, также можно написать- Ssocket->shutdown(0), # Прекращается чтение данных 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 |