Обработка сбоев подключения с помощью IO::Socket::Async

Я работаю над небольшим проектом, используя IO::Socket::Async. Я пытаюсь написать несколько тестов, чтобы убедиться, что я правильно обрабатываю потерю соединения, но мои первые попытки пошли не так, как планировалось. Я думал, что использование фазера QUIT сработает, но это не дало никакого ответа в тестах, я пытался закрыть источник, но это не дало результатов, на которые я надеялся. Может ли кто-нибудь указать мне правильное направление, как справиться с потерей соединения с помощью IO::Socket::Async?

Ниже приведен пример поставки, в которой я пытаюсь использовать функцию quit. Так как это не работает, как я ожидал. Я не уверен, правильно ли я это делаю.

supply whenever $connection -> $event {
    if $event ~~ /event message/ {
       emit { status => $event };
    }
    QUIT {
        .note;
        say 'conection lost';
    }
}

person Amuro Ray    schedule 29.10.2018    source источник
comment
stackoverflow.com/questions/50026525/ LAST { $conn.close ; } QUIT { default { $conn.close ; say "oh no, $_";}} CATCH { default { say .^name, ': ', .Str , " handled in $?LINE";}} rosettacode.org/ вики/Simple_database#Perl_6   -  person Ken Town    schedule 30.10.2018


Ответы (1)


Соединение может быть разорвано двумя способами:

  • EOF, который мы считаем «упорядоченным» закрытием. Подписка whenever очень похожа на цикл, а фазер LAST срабатывает в упорядоченном конце потока. Итак, чтобы справиться с этим случаем, используйте LAST.
  • Ошибочное завершение, такое как сброс соединения одноранговым узлом, который вызовет QUIT, как вы написали (хотя вам нужен QUIT { default { note $_ } }, чтобы фактически обработать это, как и в случае с CATCH).

Кажется, что гораздо больше случаев считаются "упорядоченными" (то есть, случай EOF), чем, по крайней мере, я ожидал. Например, запустите сервер следующим образом:

react {
    whenever IO::Socket::Async.listen('localhost', 4242) -> $conn {
        whenever $conn -> $stuff {
            $conn.print($stuff);
        }
    }
}

И такой клиент:

my $conn = await IO::Socket::Async.connect('localhost', 4242);
react {
    whenever $conn -> $stuff {
        say "Got back $stuff";
        LAST {
            say "Connection closed";
            done;
        }
        QUIT {
            default {
                say "Connection lost: $_";
                done;
            }
        }
    }

    whenever Supply.interval(1) {
        $conn.print("hello $_\n");
    }
}

Затем Ctrl+C сервер, и — по крайней мере, в моей локальной установке (Ubuntu в виртуальной машине) — это вызвало ошибку LAST. Я задавался вопросом, может ли это быть какой-то ошибкой, поэтому проследил все это до привязки ввода-вывода виртуальной машины, и нет, в этом случае мы действительно получаем EOF, передаваемый нам из операционной системы, а не ошибка. Вставить сервер на отдельную машину, а затем отключить Wi-Fi на моей локальной машине было достаточно, чтобы вызвать случай QUIT с «Сбросом соединения по узлу».

Таким образом, QUIT — это правильный способ справиться с ошибочной потерей соединения, но LAST запускается EOF, и это проявляется в некоторых случаях, которые мы можем рассматривать как «потерю соединения»; только протокол, о котором говорят поверх сокета, может действительно определить, было ли это неожиданным временем для завершения вещей.

person Jonathan Worthington    schedule 01.11.2018