8

我正在使用 IO::Socket::Async 做一个小项目。我正在尝试编写一些测试以确保我正确处理连接丢失,但我最初的尝试没有按计划进行。我认为使用 QUIT 移相器会起作用,但这在我尝试关闭供应的测试中没有给出任何响应,但这并没有给出我希望的结果。有人可以为我指出如何使用 IO::Socket::Async 处理连接丢失的正确方向吗?

下面是我尝试使用 quit 的供应示例。因为它没有按我的预期工作。我不确定我是否正确地解决了这个问题。

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

1 回答 1

5

有两种方法可以终止连接:

  • 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. 我想知道这是否可能是某种错误,因此一直追溯到 VM 的 I/O 绑定,不,在这种情况下,我们确实是从操作系统传递给我们的 EOF,而不是错误。将服务器固定在另一台机器上,然后断开我本地机器上的 wifi 连接,足以触发QUIT“对等连接重置”的情况。

总而言之,QUIT这是处理错误连接丢失的正确方法,但LAST由 EOF 触发,并且在某些情况下我们可能会考虑“连接丢失”;只有在套接字之上的协议才能真正确定这是否是事情结束的意外时间。

于 2018-11-01T00:20:24.253 回答