my $address = gethostbyname($host_name); # узнаем адрес и
my $ip_address = inet_ntoa($address); # преобразуем его
print "$ip_address $host_name\n"; # в строку
# результат: 208.201.239.36 www.perl.com
$address = inet_aton($ip_address); # и обратно
my $host_name = gethostbyaddr($address,AF_INET);# узнаем имя
print "$ip_address $host_name\n"; # по адресу
# результат: 208.201.239.36 www.perl.com
Класс IO::Socket предоставляет объектный интерфейс для встроенных функций и помогает справиться со многими трудностями и избежать некоторых ошибок при программировании передачи данных через сокеты. Максимально упрощенный пример демонстрирует написание сервера для приема сообщений по протоколу TCP:
use IO::Socket; # используем класс работы с сокетами
my $server_port = 5555; # порт для обмена
my $server = IO::Socket::INET->new( # создаем сокет
LocalPort => $server_port, # на порту
Type => SOCK_STREAM, # для потокового обмена
Proto => 'tcp', # по протоколу TCP
Listen => 10, # с 10-ю соединениями
Reuse => 1) #
or die "Ошибка запуска TCP сервера на $server_port ($@)";
while (my $client = $server->accept) { # создаем поток для
$client->autoflush(1); # клиента, очищаем буфер,
my $message = <$client>; # читаем сообщение из него
print $client "OK\n"; # посылаем ответ клиенту
close $client; # и закрываем поток
print STDERR $message; # выводим сообщение
last if $message =~ /STOP/i; # выходим из цикла, если
} # в сообщении есть STOP,
close $server; # и закрываем сокет
Сокеты могут использоваться не только для обмена данными по сети, но и для межпроцессного взаимодействия, когда сервер и клиент работают на одном и том же компьютере. Для доступа к приведенному серверу можно использовать, например, такую клиентскую программу:
use IO::Socket; # используем модуль работы с сокетами
my $server_host = '127.0.0.1'; # адрес сервера
my $server_port = 5555; # и порт на нем
my $socket = IO::Socket::INET->new( # создаем сокет
Type => SOCK_STREAM, # для потокового обмена
Proto => 'tcp', # по протоколу TCP
PeerAddr => $server_host, # с удаленным адресом
PeerPort => $server_port) # и портом
or die "Ошибка соединения с $remote_host:$remote_port ($@)";
# сообщение задается
my $message = $ARGV[0] || # параметром программы
"Проверка связи!"; # или умолчанием
print $socket "$message\n"; # отправляем его и
my $answer = <$socket>; # принимаем ответ
print "$answer"; # выводим ответ
close $socket; # и закрываем сокет
Из этого незатейливого примера можно сделать такой вывод: для согласованной работы клиент и сервер должны следовать установленным "правилам общения" во время сеанса обмена данными, так называемому протоколу прикладного уровня. В нашем случае правила сводятся к тому, что обмен идет по порту 5555, сервер ждет от клиента только одно сообщение, клиент ждет обязательного ответа от сервера, который завершает работу по получении сообщения, в котором содержится строка 'STOP'. Подробные соглашения описываются в конкретных протоколах сетевого обмена, например: HTTP (передача гипертекстовых документов), SMTP (отправка электронной почты), FTP (передача файлов). Описание подобных протоколов и других соглашений публикуются в виде предложений RFC (Request For Comment) - фактических международных стандартов, на которые ориентируются разработчики сетевого программного обеспечения.
Во Всемирной сети Интернет насчитывается огромное количество файловых серверов, где хранятся архивы программ, документация и другая информация. FTP (File Transfer Protocol) - это протокол, специально созданный для передачи файлов. Обмен файлами остается одной из постоянных задач сетевого программирования, которая легко решается средствами языка Perl. В поставке Perl имеется стандартный модуль Net::FTP, реализующий FTP-клиента, который позволяет весьма просто организовать обмен файлами с сервером по протоколу FTP - например, автоматизировать автоматическое обновление нужных файлов с сервера. Далее приводится программа, которая с помощью команд FTP загружает с сервера файл, если он имеет более позднее время изменения, чем его локальная копия:
use Net::FTP; # используем модуль работы с FTP
my $server = 'ftp.server.org'; # имя или адрес сервера
my $file = 'file.name'; # имя файла
my $ftp = Net::FTP->new($server) # соединяемся с сервером
or die "Ошибка соединения с $server:$@";
$ftp->login('ftp','ftp') # указываем имя и пароль
or die " Ошибка регистрации:", $ftp->message;
$ftp->cwd("/pub") # переходим в каталог
or die "Ошибка смены каталога:", $ftp->message;
my $time_ftp = $ftp->mdtm($file) # время изменения на сервере
or die;
my $time_old = (stat($file))[9]; # время создания копии
if ($time_ftp > $time_old) { # если файл на сервере новее,