4

使用“cro sub”创建了一个 websocket 服务器。

写了这个客户:

use v6;
use Cro::WebSocket::Client;

constant WS-PORT = '20000';
constant WS-ADDRESS = 'localhost';
constant WS-PATH = 'chat';
constant WS-URL = 'ws://' ~ WS-ADDRESS ~ ':' ~ WS-PORT ~ '/' ~ WS-PATH;
constant TIMEOUT-TO-CONNECT = 5; # seconds

my $timeout;
my $connection-attempt;

await Promise.anyof(
  $connection-attempt = Cro::WebSocket::Client.connect(WS-URL),
  $timeout = Promise.in(TIMEOUT-TO-CONNECT));

if $timeout.status == Kept
{
  say "* could not connect to server in ', TIMEOUT-TO-CONNECT, ' seconds";
  exit 1;
}

if $connection-attempt.status != Kept
{
  say "* error ", $connection-attempt.cause,
    " when trying to connect to server";
  exit 1;
}

my $connection = $connection-attempt.result;
my $peer = WS-ADDRESS ~ ':' ~ WS-PORT;
say '* connected with ', $peer;

my $counter = 0;

my $message-supplier = Supplier::Preserving.new;
my $has-message-to-send = $message-supplier.Supply;
$message-supplier.emit(1);

react
{
  whenever $has-message-to-send
  {
    $counter++;
    $connection.send($counter);
    say "* ok, sent message ", $counter, " to server"; 
  }

  whenever $connection.messages -> $reply
  {
    say '* received reply=[' ~ $reply ~ '] from server';
    $message-supplier.emit(1);
  }

} # react

我使用 tcpdump 看到来自服务器的响应代码 101(切换协议),但我没有看到从客户端发送到服务器的消息。

那么,我做错了什么?

另一个问题,"$connection.send" 不应该返回一个 Promise 什么的吗?发送时出现错误怎么办?

还有一个问题:似乎服务器只理解 IPV6 地址......如何让它理解 IPV4 地址?

就是这样,现在。


更新

按照 Takao 的建议,改变

$connection.send($counter)

$connection.send($counter.Str)

解决了这个问题(虽然我在另一个程序上试过,不是这个)。

4

1 回答 1

6

让我们一块一块地解决这个问题。

首先,您的代码对我来说看起来是正确的,除了一些微小的位。

当我复制您的代码时,它确实不起作用,所以我尝试使用cro trace .而不是cro run .. 您可以在官方文档中找到有关该模式的信息。另一种方法是只设置CRO_TRACE=1环境变量。

所以在调试过程中我看到了这个错误: [TRACE(anon 1)] Cro::HTTP::ResponseParser QUIT No applicable body serializer could be found for this message 正如它所说,您发送的正文无法序列化。所以我调查了你要发送什么:$counter$counter在您的代码中是Int,所以我们需要在Str之前制作它,做简单的事情$counter.Str会使您的示例工作。

另外,请注意,您在每次回复时都会发送一条消息,并且回显服务器(您使用创建的默认服务器cro stub)也会为每条传入消息发送回复,因此您的示例会无休止地发送消息。为了防止这种情况发生,您可以考虑添加一个条件,在该条件下您将不再发送东西,但是,无论如何,它是一个测试示例,这取决于您。

至于你的其他问题:

另一个问题,“$connection.send”不应该返回一个 Promise 什么的吗?

应该不会吧,接下来我会写出一些cro的架构细节来讲解。正如您从阅读文档中可能知道的那样,cro 管道基本上只是一堆 -包装的Cro::Transform耗材。在里面Cro::Websocket::Client::Connectionsend方法只是将一个东西直接发送到Cro::Source整个管道中,一个简单的就不会出错$supplier.emit($message)(这个方法的实际实现看起来非常接近这一行)。你碰到的事情发生在管道中。我确信隐​​藏这种情况的异常并不是一个很好的用户体验,所以我会考虑制作一个补丁来传播异常,这样会更容易捕获(尽管你总是可以使用调试模式)。

似乎服务器只理解 IPV6 地址......如何让它理解 IPV4 地址?

我不确定,请打开一个新问题。

于 2018-07-18T18:17:49.920 回答