INFOpudding - ИТ в образовании и не только
Вторник, 20.04.2021, 23:01
» Меню сайта
» Категории раздела
Общее [1]
» Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

» Форма входа
Главная » Статьи » Сетевые технологии » Общее

Принципы сетевого взаимодействия на примере простейшего echo-клиента на perl

    Если вы читаете эту статью, значит, вы пользуетесь интернетом. А интернет – это компьютерная сеть. Никогда не задумывались, как сети работают? Ну, то есть, понятно, что есть кабели, которыми компьютеры связываются между собой, еще какое-то оборудование (по секрету, это т.н. активное сетевое оборудование, коммутаторы, маршрутизаторы и т.п.), но это физическая сторона сети, а как происходит общение между двумя компьютерами?

    Для этого у них есть свои особые языки – протоколы, и если люди при встрече могут сказать «Привет! Как дела?», а в другой раз просто «Привет» (ну, нет сегодня настроения заводить долгую беседу), то языки компьютерных сетей – протоколы – такого не допускают. Беседы должны быть «протокольными» (простите за каламбур), т.е. каждый из них четко знает, что он должен сказать, и приблизительно ожидает, что ему ответят. Если на вопрос «Как погода?» в ответ придет «Меня зовут Саша» - разговор этот не сладится.

    В этом и суть протокола: процесс установки соединения для передачи данных четко оговорен давным-давно и изложен в RFC (Request for Comments), все эти документы есть в свободном доступе, большая часть из них переведена на русский язык, и с ними можно ознакомиться, например, здесь  (английские оригиналы) или здесь (русский репозиторий).

    Один из этих документов описывает протокол Echo, суть которого, как следует из его названия («Эхо») – дублировать полученные от клиента данные. Для чего? Об этом было бы лучше спросить создателя протокола и автора соответсвующего RFC862 (http://rfc.com.ru/rfc862.htm) Джона Постела (J.Postel), но для нас в рамках этой обзорной статьи, это не столь уж и важно (да и почил он ныне). Но можно предположить, что протокол этот пригодится при тестировании соединения, например, мы что-то послали серверу, и нам в ответ это же и вернулось, значит там есть-таки кто-то живой.

    Теперь перейдем к самому важному и интересному. Напишем свой echo-клиент. Этот клиент будет отправлять на указанный нами echo-сервер строки, которые мы будем вводить, и выводить полученные от сервера данные, т.е. те же самые строки, а в конце – для проверки – выведет еще и количество посланных и принятых байтов, чтобы мы, увидев, что числа эти равны, окончательно убедились, что это было живое общение с сервером, а не с собой.

    Итак, писать свой echo-клиент мы будем на perl`е. Почему именно на нем? Во-первых, perl идеально подходит для написания сетевых програм, в нем уже есть мощная поддержка сетевого стека TCP/IP, а при необходимости модули для получения дополнительного функционала ваших программ всегда можно загрузить на сайте CPAN. Ну, и во-вторых, потому что я сам немного пишу на этом языке.

    Приступим. Писать код можно в любом текстовом редакторе, если хотите, даже в Блокноте. Но лично я предпочитаю gvim, одним из неоспоримых достоинств которого  является проверка синтаксиса многих языков программирования, в том числе и perl`а.


Для начала подключим необходимые модули:

Для проверки синтаксиса

use strict;

для работы с сетевыми сокетами Berkeley

use Socket;

для использования функции autoflush, что позволит передавать данные сразу же, не копируя их в буфер.

use IO::Handle;

Теперь опишем переменные. ($bytes_out,$bytes_in – это счетчики соответственно отправленных и принятых байтов. Пока они у нас обнулены, мы еще ничего в сеть не отправляли и ничего оттуда не получили.

my ($bytes_out,$bytes_in) = (0,0);

$host – это ip-адрес того echo-сервера, к которому му будем стучаться. Мы получаем этот адрес либо как параметр программы при запуске (shift), либо, если он не был введен, используем наш компьютер в качестве echo-сервера. Здесь нужно оговориться, что операционная система Windows не имеет своего встроенного echo-сервера, поэтому, чтобы проверить работу этого скрипта, мне пришлось включить echo-сервер на одном из моих серверов под управлением ОС FreeBSD.

my $host = shift || 'localhost';

$port – сетевой порт, на которм слушает и ждет соединения echo-сервер. Мы либо вводим номер порта, либо он назначается автоматически как результат функции getservbyname, которой передается символическое имя протокола – echo и имя протокола нижнего уровня – tcp – через который и работает echo.

my $port = shift || getservbyname ('echo','tcp');

$protocol – номер порта tcp, полученный преобразованием его имени функцией getprotobynamе

my $protocol = getprotobyname ('tcp');

Преобразуем ip-адрес нашего сервера в двоичную форму функцией inet_aton. В случае ошибки преобразования будет выведено соответствующее предупреждение и программа аварийно завершится.

$host = inet_aton($host) or die "$host: unknown host";

Открываем сокет – канал межсетевого взаимодействия на логическом уровне. Для этого функции socket передаем четыре параметра: имя сокета, чтобы его в дальнейшем идентифицировать (мы ведь можем открыть несколько сокетов одновременно, именно так мы и работаем в интернете: через один сокет странички смотрим, через другой с FTP-сервера программу качаем и т.д.), второй параметр – т.н. домен протоколов, для нас тут важно просто знать, что мы используем стек TCP/IP, поэтому имя домена протокола -  AF_INET, третий параметр – тип протокола – потоковый (TCP) или дейтаграммный (UDP), мы используем TCP – поэтому пишем SOCK_STREAM, последний – protocol – номер порта TCP. Опять же, в случае проблем – вывод ошибки и выход из программы.

socket (SOCK, AF_INET, SOCK_STREAM, $protocol) or die "Can`t open socket: $!";

Определяем структуру destination_address, состоящую из пары двоичных чисел – порт и адрес хоста.

my $destination_address = sockaddr_in($port,$host);

Все подготовительные этапы пройдены, можем открывать соединение.

connect (SOCK, $destination_address) or die "Connection failed: $!";


Включаем  для нашего открытого сокета автосброс – будем слать напрямую, минуя буфер.

SOCK->autoflush(1);

Теперь, собственно, сам процесс общения с сервером.

Цикл будет работать, пока мы не выйдем, например, через Ctrl+D (в Windows) или Ctrl+Z (в UNIX). В цикле читается стандартный ввод – клавиатура, и все, что введено, отправляется в открытый сокет SOCK – т.е. на echo-сервер, который мы определили.

while (my $message_out = <>){

    print SOCK $message_out;

Теперь читаем из сокета то, что пришло в ответ

    my $message_in = <SOCK>;

Печатаем это в стандартный вывод – на экран

    print $message_in;

Подсчитываем количество принятых и отправленных байтов

    $bytes_in +=length($message_in);

  $bytes_out +=length($message_out);

}


Закрываем сокет

close SOCK;

Печатаем в стандартный вывод ошибок  количество принятых и отправленных байтов

print STDERR "bytes_sent = $bytes_out, bytes_received = $bytes_in\n";    


    Вот и все. Только что мы написали простейший сетевой клиент. Простейший он потому, что сам протокол, реализацию которого мы изобразили, простой донельзя. Конечно же, почтовый клиент или FTP-клиент будут заметно сложнее, но об этом мы поговорим как-нибудь в другой раз.



Категория: Общее | Добавил: anna (03.09.2011) | Автор: Константин
Просмотров: 1054 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
» Поиск
» Учебные заведения
Брянский государственный университет академика И.Г. Петровского Брянская государственная инженерно-технологическая академия
Copyright MyCorp © 2021|Бесплатный конструктор сайтов - uCoz