Добрый день всем.
Подскажите начинающему ...Пробую написать на perl TCP сервер и запустить через xinetd на FreeBSD:
фрагмент tcp_srv.pl:
//----
open(LogFile, ">>$logfile") || die "Can't open file $logfile";
print LogFile "Begin\n";local $SIG{ALRM} = sub
{ print LogFile "Exiting due TimeOut";
close LogFile;
die "Alarm"; };
alarm 10;print STDOUT "READY\r\n";
print LogFile "Sent READY\n";while(<>)
{
print STDOUT "READY\r\n";
print LogFile "Sent READY\n";
}
фрагмент xinetd.conf:
//----
service tcp_srv
{
log_type = FILE /usr/local/tcp_srv/tcp_srv_log
disable = no
type = UNLISTED
socket_type = stream
protocol = tcp
wait = no
user = root
server = /usr/local/tcp_srv/tcp_srv.pl
port = 3838
log_on_success += USERID
}
//----захожу телнетом на 3838 порт и такое ощущение что вывод (print STDOUT) кешируется,
т.е. на мои ENTER-ы ничего не выводится, а через 10 сек (по аларму) выбрасывается на экран множество READY на все раннее введенные ENTER-ы и конечно дисконнект.Самое смешное, что если "print STDOUT" заменить на "print STDERR" в перле, то работает так, как я и ожидал :) , т.е. на каждый ENTER в телнете выдает READY.
Подскажите, в чем может быть проблема.
Вот как всегда ...
стоило написать вопрос, как вскоре нашел сам ответ:установил системную переменную
$| = 1
и проблема снята.
Ну тогда на будущее(вдруг захотите написать standalone) еще несколько моментов:
1. $| устанавливает autoflush только для текущего хендлера вывода, а не для всех хендлеров.
2. IO::Handle и наследуемый из него IO::Socket позволяет установить значение autoflush для любого хендлера, а не только STDOUT
3. Если не хочется подгружать сотни строк кода от IO::Handle, то можно сделать произвольный хендлер текущим, а потом при желании(для tcp демона зачастую возврат к STDOUT не нужен) вернутся к STDOUT: select($somehandler);$|=1;select(STDOUT).
4. Использование bareword для хендлеров нежелательно, лучше для этого обыкновенные скаляры:
open my $somehandler, ...
socket (my $sock,...)