Войти
VTEM SlideshowVTEM SlideshowVTEM Slideshow


Perl и работа с сокетами

 

Иногда есть потребность из программы на Perl соединиться с другими сервероми и передать или принять какую то информацию. Почти всегда возникает потребность работать с протоколом HTTP, но узнав принципы взаимодействия между серверами и прочитав спецификацию данного протокола, можно просто написать программу, работающую через любой протокол. В дальнейшем мы рассмотрим работу с протоколом HTTP.
Нам понадобится  - сокеты (sockets). Сокет -  канал, проложенный между сервером на котором запускается программа и сервером, с которым хотим установить соединение. Для работы с сокетами в Perl есть модуль - Socket.
Для создания сокета используют функцию socket. Формат у нее таков:

socket(SOCK, DOMAIN, TYPE, PROTOCOL);

Эта функция открывает сокет и привязывает его к указателю SOCK.

  • DOMAIN - это коммуникационный домен. Не нужно его путать с доменом хостинга с которым соединяемся. В даном случае это будет Internet домен (бывает еще Unix) и по этому указываем: PF_INET
  • TYPE - тип соккета. Мы будем использовать SOCK_STREAM - этот тип обеспечивает последовательный и надежный поток байтов. Еще  существуют Datagram socket и Raw socket, но о них в другой раз.
  • PROTOCOL - протокол, по которому будет устанавливаться соединение. В этом случае это tcp поэтому вместо PROTOCOL прописываем это:
getprotobyname('tcp');

Помимо tcp можно также использовать udp, ip и т.д. Функция getprotobyname возвращает название протокола в удобном для функции socket виде.
Создаем сокет:

socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));

Когда сокет готов, можно подключаться к определенному серверу. Для этого необходим адрес сервера и порт. Предварительно, необходимо сделать это:

# Конвертирует имя сервера в бинарную последовательность.
$iaddr = inet_aton($host);
# Упаковывает все в понятную функции connect последовательность.
$paddr = sockaddr_in($port, $iaddr);

Все готово и можем использовать функцию connect:

connect(SOCK, $paddr);

После соединения с сервером, можем передавать и принимать определенную информацию. Рассмотрим процесс передачи и приема данных, подробнее, на примере соединения с Web-хостингом и получения с него определенного документа. Для отправки сообщения через сокет служит функция send:

send (SOCK, "То что шлем", 0);

Вместо 0 может быть один из этих флагов:
MSG_OOB - Посылать/получать данные для сокетов типа SOCK_STREAM
MSG_DONTROUTE - Посылать данные без маршрутизации пакетов. Используется диагностическими программами и процессами управляющими таблицами маршрутизации.
Для приема данных через сокет, используем стандартную операцию:

@data=<SOCK>;

После окончания связи, нужно закрыть сокет, при этом серверу говорится, что сеанс связи закончен. Для закрытия сокета есть функция close, которой нужно передать дескриптор сокета.

close(SOCK);

На последок пример рабочего кода. Программа соединяется с сервером www.perl.ru и забирает от туда главную страницу.

use Socket;

$host="www.perl.ru";
$port="80";

socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));

$iaddr = inet_aton($host);
$paddr = sockaddr_in($port, $iaddr);

connect(SOCK, $paddr);
send (SOCK, "GET / HTTP/1.0\n\n", 0);

@data=<SOCK>;

close(SOCK);

print @data;

Если попробуете изменить значения переменной $host, то увидите, что с некоторых серверов поступает сообщение об ошибке. Всему причиной есть HTTP протокол и настройки Web-серверов. Подробнее о HTTP читайте в посте "HTTP протокол". Пока о том как с этим бороться.
Это происходит потому, что в сети существует большое количество виртуальных серверов, то есть серверов с различными именами, но одним IP. Попробуйте сделать Ping Любое_имя.narod.ru. Они будут иметь один IP адрес. А поскольку данный сокет фактически соединяется с IP , то и получаем известие об ошибке. Веб сервер того же narod.ru просто напросто не знает страницы какого из виртуальных серверов показать. Значит необходимо объяснить ему. Для этого есть переменная HOST которая указывается в заголовке запроса. Т.е.

send (SOCK, "GET / HTTP/1.0\nHOST:$host\n\n", 0);

Подставив данную строчку в наш скрипт, получим уже совершенную программу. Некоторые сервера в зависимости от браузера (вы еще не ощущаете себя браузером?) показывают различные версии сайтов. Встречается это очень крайне редко, но к этому нужно готовится. Используйте переменную USER-AGENT.


Hosting tools

Who's Online

Сейчас 16 гостей и ни одного зарегистрированного пользователя на сайте