Анимация
JavaScript
|
Главная Библионтека Хотя гнезда изначально разрабатывались для Berkeley UNIX, все возрастающая популярность Internet побудила практически всех поставщиков операционных систем включить в свои продукты поддержку гнезд для программирования систем клиент/сервер. Функция socket является относительно низкоуровневой, а мы в нащей книге рассматриваем в основном высокоуровневые средства Perl. Рекомендуем вам пользоваться более удобным модулем IO:;Socket*, который мы будем применять во всех наших примерах. Это значит, что мы также будем применять некоторые объектно-ориентированные конструкции Perl. Краткое введение в эти конструкции дано в главе 19. Более подробное введение в объектно-ориентированное программирование на Perl приведено на тап-странице perltoot(l) и в главе 5 книги Programming Perl. Подробное рассмотрение TCP/IP выходит за рамки нашей книги, но мы можем представить хотя бы несколько простых клиентов. О серверах, которые более сложны, вы можете узнать в главе 6 книги Programming Perl и на тап-странице регИрс( 1). Простой клиент Для нашего простейшего клиента мы выберем довольно скучный сервис, который называется daytime ("время суток"). Сервер времени суток посылает установившему соединение клиенту одну строку данных, содержащую значение времени суток на этом удаленном сервере, а затем закрывает соединение. Вот клиент: #/usr/bm/perl -w use 10::Socket; $remote = 10::Socket::INET->new ( Proto => "tcp", PeerAddr => "localhost", PeerPort => "daytime(13)", ) or die "cannot connect to daytime port at localliost"; while ( <$remote> ) { print } Запустив эту программу, вы должны получить с сервера примерно следующее: Thu May 8 11:57:15 1997 lOiSocket входит в состав стандартного дистрибутива Perl версии 5 004 Если у вас более ранняя версия, получите этот модуль из CPAN, где вы найдете модули с простыми интерфейсами к следующим сервисам: DNS, ftp, Ident(RFC 931), NIS и NISPlus, NNTP. ping, POP3, SMTP, SNMP, SSLeay, telnet, time и др. Вот что означают параметры конструктора new Proto Протокол, который следует использовать В данном случае возвращенный дескриптор гнезда будет подключен к ТСР-гнезду, потому что нам нужно потоковое соединение, т е соединение, которое работает почти так же, как старый добрый файл Не все гнезда такие Например, с помощью протокола UDP можно создать дейтаграммное гнездо, используемое для передачи сообщений PeerAddr Имя или Internet-адрес удаленного хоста, на котором работает сервер Мы могли бы указать имя подлиннее, например www perl com, или адрес вроде 204 148 40 9 Однако для демонстрационных целей мы использовали специальное хост-имя localhost, которое всегда должно обозначать мащину, на которой вы работаете Имени localhost соответствует Internet-адрес 727001 PeerPort Имя или номер порта сервиса, с которым мы хотим соединиться В системах с нормально конфигурированным системным файлом сервисов* мы могли бы обойтись просто именем daytime, но на всякий случаи мы все же дали в круглых скобках номер порта (13) Использование одного номера без имени тоже сработало бы, но осторожные программисты стараются не использовать числа вместо констант Вы обратили внимание на то, как возвращаемое значение конструктора new используется в роли дескриптора файла в цикле while Это то, что называется косвенным дескриптором файла - скалярная переменная, содержащая дескриптор файла Его можно использовать точно так же, как обычный дескриптор Например, так из него можно прочитать одну строку $line = <$handle>, так - все остальные строки @lines = <?handle>, а так - послать в него строку данных print $handle "some data\n". Системный файл сервисов в UNIX находится в каталоге /etc/services Клиент webget Вот простой клиент, который устанавливает соединение с удаленным сервером и получает с него список документов. Этот клиент интереснее предьщущего, потому что перед получением ответа сервера он посылает на него строку данных. # I /usr/bm/perl -w use 10::Socket; unless (@ARGV > 1) { die "usage: $0 host document " } $host = shift(@ARGV); foreach $document ( @ARGV ) { $remote = 10::Socket::INET->new { Proto => "tcp", PeerAddr => $host, PeerPort => "http(80)", unless ($remote) { die "cannot connect to http daemon on $host" ) $remote->autoflush(1); print $remote "GET $document HTTP/1.0\n\n"; while { <$remote> ) { print } -close $remote; } Подразумевается, что Web-сервер, на котором работает сервис http, использует свой стандартный порт (номер 80). Если сервер, с которым вы пытаетесь установить соединение, использует другой порт (скажем, 8080), то в качестве третьего аргумента конструктора new () нужно указать PeerPort => 8080. При работе с этим гнездом применяется метод autoflush, потому что в противном случае система буферизировала бы выходную информацию, которую мы ей передали. (Если у вас компьютер Macintosh, то нужно заменить все \п в коде, предназначенном для передачи данные по сети, на \015\012.) Соединение с сервером - это лишь первый этап процесса: установив соединение, вы должны начать говорить на языке этого сервера. Каждый сервер сети использует свой собственный маленький командный язык, и входные данные, подаваемые на сервер, должны быть сформулированы именно на этом языке. Начинающаяся словом GET строка, которую мы послали серверу, соответствует синтаксису протокола HTTP. В данном случае мы просто запрашиваем каждый из указанных документов. Да, мы действительно создаем новое соединение для каждого документа, несмотря на то, что это тот же самый хост. Именно так функционирует НТТР-серевер. (Последние версии Web-броузеров могут требовать, чтобы удаленный сервер оставлял соединение открытым на некоторое время, но сервер не обязан удовлетворять такой запрос.) 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 |