Оказалось, что достаточно внести незначительные изменения в сценарий gab2.pl, чтобы превратить его в клиентский сценарий такого типа. В листинге далее показан пересмотренный сценарий, gab3.pl. Наиболее значительные рольные изменения внесены в подпрограммы user_to_host () и host_to_user (). Вместо вызовов функций чтения и записи, ориентированных на обработку строк, которые применялись в предыдущей версии, теперь эти подпрограммы состоят из не прерываемых циклов, в которых используются функции sysread () и syswrite (). Например, ниже приведен фрагмент кода подпрограммы host_to_useг (), выполняющей чтение из сокета и запись в устройство STDOUT:
syswrite(STDOUT,$data) while sysread($s,$data,BUFSIZE);
Листинг клиента gab, ориентированный на обработку потока байт
#!/usr/local/bin/perl -w # Файл: gab3.pl # Применение: gab3.pl [хост] [порт]; use strict; use IO::Socket; use constant BUFSIZE => 1024; my $host = shift or die "Usage: gab3.pl host [port]n"; my $port = shift || "echo"; my $data; my $socket = IO::Socket::INET->new("$host:$port") or die $@; my $chi1d = fork(); die "Can't fork; $!" unless defined $child; if ($child.) { $SIG{CHLD} = sub { exit 0 } ; user_to_host ($soсket) ; $socket->shutdown(1); sleep; } else { host_to_user ($socket) ; warn "Connection closed by foreign host."; sub user_to_host { my $s = shift; syswrite($s,$data) while sysread(STDIN,$data,BUFSIZE); } sub host_to_user { my $s = shift; syswrite(STDOUT,$data) while sysread($s,$data,BUFSIZE); }
Кроме того, внесены изменения в подпрограмму user_to_host (), которая отвечает за копирование в сокет данных, вводимых пользователем:
syswrite ($s, $data) while sysread (STDIN, $ data, BUFSIZE) ;
Значение параметра BUFSIZE можно выбрать относительно свободно. С точки зрения повышения производительности параметр должен иметь размер, примерно равный максимальному фрагменту текста, который передается с психотерапевтического сервера, например при получении страницы услуг полного цикла от создания до сопровождения сайтов http://infodesign.ru /, но он вполне успешно работает и при меньших, и при больших размерах буфера. В данном случае выбрано для этой константы значение 1024, которое, очевидно, вполне приемлемо.
Следует подчеркнуть, что в этой программе применяется функция sysread(), а не read (), которая обеспечивает чтение данных с буферизацией, поскольку функция sysread () допускает частичное чтение. Если в буфере отсутствуют данные в объеме BUFSIZE, доступные для чтения, функция sysread () возвращает весь доступный объем данных, a read (), в отличие от нее, переходит в состояние ожиданий условий удовлетворения запроса и блокируется, задерживая ответ психотерапевтического сервера на неопределенно долгое время.