LINUX.ORG.RU

Задание на Stepik по Perl. Никак не могу понять, где загвоздка. HELP.

 ,


0

3

Текст задания:

Запустите на 8080 порту tcp сервер, который будет принимать данные от клиента и выводить их на STDOUT, а когда получит сообщение «exit» перестанет работать.

Мое решение, работает под линухом на локальной виртуалке:

use strict;
use IO::Socket;
setpgrp(0,0);
my $general_ppid = $$;  # print $general_ppid."\n";
my $server = IO::Socket::INET->new(
    LocalPort => 8080,
    Type      => SOCK_STREAM,
    ReuseAddr => 1,
    Listen    => 10)
or die "Can't create server on port 8080 : $@ $/";
while (my $client = $server->accept()) {
my $child = fork();
if ($child) { close($client); next }
if (defined $child) {
close( $server );
$client->autoflush(1);
my $message;
do {
  if (defined (my $message1 = <$client>))
  { chomp $message1; $message = $message1; }
  else { last ; }
  if ($message eq "exit") { kill -2, 0 }
  else { print $message."\n"; }
} while (1);
close( $client );
exit;
} else { die "Can't fork^ $!"; }
}

В окне вывода Stepik появляется ошибка:

Failed. Runtime error Error:

Вопрос: где что не так?

★★★★★

setpgrp(0,0); может это лучше убрать ?

pinachet ★★★★★
()

setpgrp(0,0) нужен для kill(-2,0)

Если подключиться к порту и ничего не посылая закрыть соединение - будет ошибка?

добавь отладочный вывод пред чтением и после «$!»

close() не может давать такое сообщение если коннект уже потерян?

PS хорошо бы еще shutdown($socket, 2); делать.

vel ★★★★★
()
Последнее исправление: vel (всего исправлений: 1)

Число тестирующих клиентов известно? Нет ли там при тестировании серьезных ограничений на число процессов/файловых десткипторов?

Не виндузятники ли там которые хотят \r\n? Я бы попробовал проверять по /^exit/i

vel ★★★★★
()
Ответ на: комментарий от vel

Если подключиться к порту и ничего не посылая закрыть соединение - будет ошибка?

Нет, не будет. Я это предусмотрел в алгоритме, см. else { last ; }

добавь отладочный вывод пред чтением и после «$!»

ошибка Illegal Seek - появляется сразу после

my $server = IO::Socket::INET->new(
и никуда не исчезает дальше.

close() не может давать такое сообщение если коннект уже потерян?

у меня все работает локально. даже несмотря на ошибку Illegal Seek выше

PS хорошо бы еще shutdown($socket, 2); делать.

это надо родителю как-то сказать, потомок закрывает $server сразу, и работает только с $client.

Infra_HDC ★★★★★
() автор топика
Последнее исправление: Infra_HDC (всего исправлений: 1)
Ответ на: комментарий от vel

Не виндузятники ли там которые хотят \r\n? Я бы попробовал проверять по /^exit/i

он бы ругался на setpgrp(0,0);, так как оно Unimplemented в виндосе

Infra_HDC ★★★★★
() автор топика
Ответ на: комментарий от vel

Не виндузятники ли там которые хотят \r\n? Я бы попробовал проверять по /^exit/i

Походу, chomp отрабатывает ОК и в винде, и в линухе.

Infra_HDC ★★★★★
() автор топика
Ответ на: комментарий от unstable-case

В таких простых примерах мне достаточно Far Manager или GNU nano. дебажу perl -c scriptname.pl и сообщения на STDOUT/STDERR во время выполнения.

UPD: эту задачу еще nc -vvv в силу сетевой специфики дергал.

Infra_HDC ★★★★★
() автор топика
Последнее исправление: Infra_HDC (всего исправлений: 1)
Ответ на: комментарий от unstable-case

В фаре подсветка есть, причем из коробки, то есть не ставя никаких плагинов и не делая никаких дополнительных настроек: https://www.dropbox.com/s/f7vhs6pmwwqomfb/%D0%A1%D0%BA%D1%80%D0%B8%D0%BD%D1%88%D0%BE%D1%82%202020-07-30%2012.39.59.png?dl=0

Infra_HDC ★★★★★
() автор топика
Ответ на: комментарий от vel

кстати да, не знал. спасибо за инфу

Infra_HDC ★★★★★
() автор топика
Ответ на: комментарий от unstable-case

Для извлечения данных и составления отчетов.

Infra_HDC ★★★★★
() автор топика

Как оказалось, многопоточность была излишней, и вот правильное решение, которое принято обучающей системой:

use strict;
use IO::Socket;
my $server = IO::Socket::INET->new(
    LocalPort => 8080,
    Type      => SOCK_STREAM,
    ReuseAddr => 1,
    Listen    => 10)
or die "Can't create server on port 8080 : $@ $/";
my $client = $server->accept();
$client->autoflush(1);
my $message;
A2: { do {
  if (defined (my $message1 = <$client>))
  { chomp $message1; $message = $message1; }
  else { last A2; }
  if ($message eq "exit") { last A2; }
  else { print $message."\n"; }
} while (1); }
close( $client );
close($server);
</thread>

Infra_HDC ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.