Perl и сокеты. Часть 2 (95,45%)
В статье рассматривается работа с сокетами на Perl с помощью стандартного модуля Socket на примере клиента, получающего данные о погоде с weather.yandex.ru. А также работа с сокетами через модуль IO::Socket на примере клиента службы времени…
Skype: весь мир может болтать бесплатно! (38,71%)
Главное преимущества разговора через интернет - это бесплатные звонки с компьютера на компьютер, т.е. Вы можете позвонить в любую точку мира совершенно бесплатно! Далее Вы узнаете обо всем, что необходимо для разговора по интернету. Вам необходимы две составляющие: Первая составляющая - это программа для общения в сети. Существует несколько…
Как правильно создать сайт (37,5%)
В первую очередь хочется отметить, что при заказе на разработку и создание сайта в большинстве случаев заказчик сам толком не знает, чего хочет. Начиная работу по созданию сайта необходимо руководствоваться следующими критериями и этапами: - Каркас сайта (т.е. заказчик и исполнитель должны полностью понять друг друга, при этом исполнитель,…
В этой статье рассматривается один из способов взаимодействия с сокетами языка Perl с помощью стандартного модуля Socket. Предполагается, что читатель знаком с базовым синтаксисом Perl и стеком протоколов TCP/IP, поэтому углубляться в эту тему я не стану. Если вас что-то интересует из вышеперечисленного, спросите у googl'a. Итак, приступим.
Для начала разберемся, что из себя представляет этот загадочный «сокет». Сокет — это конечная точка соединения, можно сказать, «канал», по которому мы можем «общаться» с удаленным процессом, отправляя и получая требуемые сообщения. Для чего это нужно? Для обмена данными с удаленной машиной. Зачем? Что ж, давайте разбираться, но по порядку. Рассмотрим устройство сокета:
- Домен сокета:
В книге «Разработка сетевых программ на Perl», написанной небезызвестным Линкольном Штайном, на мой взгляд, было дано наиболее точное и понятное определения термина «домен сокета»: «Домен сокета определяет семейство сетевых протоколов и схем адресации, поддерживаемых константами». На данный момент существует лишь два общепринятых домена: AF_INET, применяющийся для работы с сетями TCP/IP, и AF_UNIX, применяющийся для межпроцессного взаимодействия на одном хосте (данный домен может быть реализован и на системах, отличных от UNIX). - Тип сокета:
Определяет особенности связи через сокет. Это может быть как непрерывный поток данных (SOCK_STREAM), так и данные, передаваемые отдельными пакетами (SOCK_DGRAM). Язык Perl также поддерживается доступ к внутренним протоколам и интерфейсам через константу SOCK_ROW, поддерживаемую через модуль Net::Raw. - Протокол сокета:
Думаю, это пояснять не стоит, как и тот факт, что протоколы обозначаются фиксированными целыми числами. Протоколы TCP и UDP поддерживаются API-интерфейсом языка, ICMP можно подключить через модуль Net::ICMP, raw можно подключить через Net::Raw.
Сокеты бывают дейтаграмными (обеспечивают ненадежную передачу данных без установления соединения — протокол UDP) и потоковые (напротив, обеспечивают надежную упорядоченную передачу данных в виде потока данных, устанавливая постоянное соединение).
Вы еще не устали от теории? Давайте перейдем к практике. Чтобы понять основы основ, придется написать практически бесполезный скрипт клиента службы времени, который выдает текущую дату и время. Делать мы это будем через протокол daytime (RFC867). Что ж, приступим:
#!/usr/bin/perl
use strict;
# подключаем модуль Socket
use Socket;
# далее мы вводим константу, содержащую
# адрес сервера, к которому мы должны подключиться.
# но, чтобы корректно сформировать адрес сокета,
# мы должны ввести IP-адрес требуемого хоста. т.е.
# если я хочу подключиться к s2.daytime.net.ru,
# то мне придется написать:
# use constant DEF_ADDR => '217.20.189.83'
# (это ip-адрес хоста s1.daytime.net.ru).
use constant DEF_ADDR => '212.9.235.98';
# далее вводим константу PORT, которая будет содержать
# номер порта, к которому мы будем подключаться.
# в данном случае используется протокол TCP, имеющий
# стандартный номер порта — 13.
use constant PORT => 13;
# чтобы создать соединение с сокетом, нужно определить
# протокол, с которым будем работать. к сожалению,
# мы не можем написать просто 'TCP', программа нас
# не поймет, для нее это просто очередной набор
# символов. по некоторым непонятным мне причинам
# каждый протокол имеет свой фиксированный номер.
# у протокола TCP этот номер равен 6. данное число
# говорит программе при соединении с сокетом, что мы хотим
# использовать именно TCP, а не UDP или какой-либо еще.
use constant TCP => 6;
# здесь предоставляется возможность пользователю ввести
# адрес того хоста, к которому он хочет подключиться.
# если ничего не введено, программа будет использовать
# стандартный адрес.
my $addr = shift || DEF_ADDR;
# как я уже упоминал, адрес сокета включает в себя
# номер порта и ip-адрес хоста, к которому мы собираемся
# подключиться. но, по сложившимся обстоятельствам,
# для связи используются ip-адреса в двоичном виде,
# так легче машинам, однако, представляете, каково
# читать такое человеку? естественно легче воспринимать
# что-нибудь вроде того же 127.0.0.1. чтобы перевести
# привычный нам ip в понятный программе двоичный вид, мы
# используем функцию inet_aton(arg),
# где arg — «человеческий» ip-адрес.
# (кстати, чтобы перевести двичный ip в человеческий можно
# использовать функцию inet_ntoa,
# my $ip = inet_ntoa($packed_ip),
# где $packed_ip — двоичный адрес).
my $packed_addr = inet_aton($addr);
# теперь нужно сформировать адрес сокета,
# что делается с помощью функции
# my $socket_addr = sockaddr_in($port, $packed_addr),
# которая «объединяет» номер порта($port)
# и двоичный ip-адрес($packed_addr) в формат,
# понятный для сокета.
# кстати, чтобы распаковать $socket_addr обратно
# в номер порта и двоичный ip-адрес, можно использовать
# эту же функцию, только в списковом контексте:
# my ($port, $packed_addr) = sockaddr_in($socket_addr).
my $socket_addr = sockaddr_in(PORT, $packed_addr);
# далее требуется создать сокет с помощью функции
# socket(DESCR, SOCK_DOMEN, SOCK_TYPE, PROTOCOL),
# где DESCR — дескриптор, SOCK_DOMEN — домен сокета,
# SOCK_TYPE — тип сокета,
# PROTOCOL — номер используемого протокола.
socket(SOCK, AF_INET, SOCK_STREAM, TCP) or
die "не удалось создать к сокет =(";
# после того, как мы создали сокет, можно
# устанавливать соединение с удаленным хостом.
# для этого используем функцию
# connect(DESCR, $socket_addr),
# где DESCR — дескриптор созданного сокета,
# а $socket_addr — созданный адрес сокета.
connect(SOCK, $socket_addr) or
die "не могу подключиться к сокету =(";
# запишем полученные данные в переменную
# и закроем соединение
my $date = <SOCK>;
close SOCK;
# серверы daytime возвращают время по Гринвичу
print "$date\n";
Вот и все. Осталось запустить скрипт (пусть он будет назван socket.pl):
$ ./socket.pl
Sat Jun 11 00:09:03 2005
Все. Лично я постоянно путаюсь с числовыми значениями протоколов, номерами портов, ip-адресами и прочими вещами, которые нужно запоминать. К счастью, Perl освобождает нас от всего этого несколькими полезными функциями. Запомнить их намного легче, чем все вышеперечисленное.
my $packed_addr = gethostbyname($name), где $name — имя хоста, к которому мы хотим подключиться. Например, если мы напишем my $packed_addr = gethostbyname('s2.daytime.net.ru'), то переменная $packed_addr будет содержать ip-адрес s2.daytime.net.ru в двоичном виде.
$port_number = getprotobyname($protocol), где $protocol является именем требуемого протокола. Например, если $port = getprotobyname('tcp'); $port будет содержать число 6.
$port = getservbyname($service, $protocol), где $service — имя сервиса, а $protocol — имя протокола. Данная функция возвращает номер порта. Т.о. если мы напишем $port = getservbyname('daytime', 'tcp'), переменная $port будет содержать 13.
$service = getservbyport($port, $protocol), где $port — номер порта, а $protocol — имя протокола. Функция возвращает название службы, соответствующей введенным данным. Например, в случае $service = getservbyport(13, 'tcp'), $service будет содержать 'daytime';
А теперь перепишем нашу программу, используя полученные знания о новых функциях:
#!/usr/bin/perl
use strict;
use Socket;
# имя сервера
use constant DEF_ADDR => 's2.daytime.net.ru';
my $packed_addr = gethostbyname(shift || DEF_ADDR) or
die "не могу найти данный хост =(";
my $protocol = getprotobyname('tcp');
my $port = getservbyname('daytime', 'tcp') or
die "не могу обнаружить порт =(";
my $socket_addr = sockaddr_in($port, $packed_addr);
socket(SOCK, AF_INET, SOCK_STREAM, $protocol) or
die "не могу создать сокет =(";
connect(SOCK, $socket_addr) or
die "не могу соединится с сокетом =(";
my $date = <SOCK>;
close SOCK;
print "$date\n";
Вот и все. В следующей статье напишем нечто более полезное и научимся использовать гораздо более простой способ взаимодействия с сокетами, реализуемый модулем IO::Socket.
Как приобретать б/у ноутбук (36,73%)
Рынок подержанного оборудования существует уже очень давно. Он появился на следующий день после рождения обычного рынка, на котором продаются новые товары. Существует множество причин, почему люди хотят продать свои вещи, бывшие в употреблении, но существует только одна причина, по которой б/у товары покупаются - желание сэкономить. Если…
Миф о специалисте (35,9%)
Один из специалистов по продажам в интернет жалуется другому: знаешь, вот я провожу семинары и тренинги, чтобы научить людей зарабатывать в Сети. Я говорю им: у вас есть продукт, давайте посмотрим, как сделать его прибыльным продуктом, как изучить электронный рынок, как правильно предложить товар…а они после курса обучения начинают писать и…
История создания и раскрутки одного сайта (часть 1) (35,62%)
В этой статье мне бы хотелось поделиться с читателями своим небольшим опытом в создании и раскрутке небольшого проекта и охарактеризовать основные моменты этих процессов на примере своего сайта. Я расскажу о том, с чего начинается создание сайта, о выборе хостинга, о системах подсчета статистики и о регистрации в по в поисковых системах и каталогах…
Дайте вашим посетителям текст (35,29%)
Исследования показали, что интернет-сайты кардинальным образом отличаются от печатных изданий. В чем заключаются эти отличия, как они влияют на поведение пользователей, каким должен быть правильный контент-проект — ответы на все эти вопросы вы найдете в данной статье…
CSS: врезка к статье (33,33%)
Мы часто сталкиваемся в журналах и газетах с информационными блоками, которые визуально выделены и по смыслу несколько оторваны от основного содержания. Это не прихоть верстальщика или редактора, эти блоки давно заняли заслуженное место в бумажных изданиях. К сожалению, в интернет-публикациях врезки встречаются нечасто. О создании врезок с помощью CSS как раз и рассказывается в статье…