Изучаем Perl

       

Интерактивный клиент



Интерактивный клиент

Создать программу-клиент, которая просто читает все с сервера или посылает одну команду, получает один ответ, а затем завершает свою работу, очень легко. А как насчет создания чего-нибудь полностью интерактивного, вроде telnefi Мы имеем в виду приложение, которое позволяло бы вам набрать строку, получить ответ, набрать еще одну строку, вновь получить ответ и т.д. (В принципе, telnet обычно работает в символьном, а не в строковом режиме, но идею вы поняли.)

Этот клиент — более сложный, чем те два, с которыми мы имели дело до сих пор, но если вы работаете в системе, которая поддерживает мощный вызов fork, решение получится не слишком сложным. Установив соединение с тем сервисом, с которым вы хотите пообщаться, клонируйте свой процесс вызовом fork. Каждый из созданных идентичных процессов должен выполнить очень простое задание: родительский копирует все из гнезда на стандартный вывод, а порожденный одновременно копирует все со стандартного ввода в гнездо. Реализовать это с помощью только одного процесса было бы гораздо труднее, потому что легче написать два процесса для выполнения одной задачи, чем один процесс — для выполнения двух задач*.

Вот наш код:

#!/usr/bin/peri -w use strict;

use 10::Socket;

my ($host, $port, $kidpid, $handle, $line);

unless (8ARGV == 2 ) ( die "usage: $0 host port" ) ($host, $port) = 8ARGV;

# создать tcp-соединение с указанным хостом и портом $handle - 10::Socket::INET->new(Proto => "tcp",

PeerAddr => $host,

PeerPort => $port)

or die "can't connect to port $port on $host: $!";

$handle->autoflush(l); # и результат сразу же попадает туда print STDERR "[Connected to $host:$port]\n";

# разбить программу на два процесса-близнеца

die "can't fork: $!" unless defined ($kidpid = fork());

# блок if{( выполняется только в родительском процессе if($kidpid) (

# копировать данные из гнезда на стандартный вывод while (defined ($line = <$handle> )) f print STDOUT $line;

1

kill ("TERM",$kidpid); # послать в порожденный процесс сигнал SIGTERM >

# блок else(} выполняется только в порожденном процессе else 1

# копировать данные со стандартного ввода в гнездо while (defined ($line = <STDIN>)) ( print $handle $line;

} 1

* Принцип сохранения простоты — один из краеугольных камней не только философии UNIX, но и высококачественного проектирования программного обеспечения. Наверное, именно поэтому он распространился и на другие системы.

Функция kill в блоке if родительского процесса пошлет сигнал в наш порожденный процесс (в текущий момент работающий в блоке else), как только удаленный сервер закроет свою сторону соединения.



Содержание раздела