Интерактивный клиент
Интерактивный клиент
Создать программу-клиент, которая просто читает все с сервера или посылает одну команду, получает один ответ, а затем завершает свою работу, очень легко. А как насчет создания чего-нибудь полностью интерактивного, вроде 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), как только удаленный сервер закроет свою сторону соединения.