Cro::WebSocket::Client 无效
Cro::WebSocket::Client doesn't work
使用 "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”return 不应该是 Promise 之类的吗?发送时出错怎么办?
还有另一个问题:服务器似乎只理解 IPV6 地址...如何让它理解 IPV4 地址?
到此为止。
更新
按照 Takao 的建议,更改
$connection.send($counter)
到
$connection.send($counter.Str)
解决了问题(虽然我在另一个程序上尝试过,不是这个)。
让我们一步步解决这个问题。
首先,你的代码在我看来是正确的,除了一些小的地方。
当我复制你的代码时,它确实不起作用,所以我用cro trace .
而不是cro run .
试了一下。您可以在 official docs 中找到有关该模式的信息。
另一种方法是设置 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
创建的默认服务器)也会为每条传入消息发送回复,因此您的示例会无休止地发送消息。为了防止你可以考虑添加一个条件,在这种情况下你将不再发送东西,但是好吧,这无论如何是一个测试示例,所以由你决定。
关于您的其他问题:
Another question, shoudn't "$connection.send" return a Promise or something?
应该不会吧,接下来我会把cro的架构细节写出来解释一下。正如您可能通过阅读 docs 了解到的那样,cro 管道基本上只是一堆 Cro::Transform
包装的供应品。在 Cro::Websocket::Client::Connection
内部,send
方法只是将一个东西直接发送到整个管道的 Cro::Source
中,简单的 $supplier.emit($message)
你不会出错(这个方法的真正实现看起来非常接近这条线)。您遇到的事情发生在管道的更深处。我确信隐藏这种情况的异常不是一个好的用户体验,所以我会考虑制作一个补丁来传播异常,这样它会更容易捕获(尽管你总是可以使用调试模式)。
it seems the server only understands IPV6 addresses...how to make it understand IPV4 addresses ?
我不太确定,请打开一个新问题。
使用 "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”return 不应该是 Promise 之类的吗?发送时出错怎么办?
还有另一个问题:服务器似乎只理解 IPV6 地址...如何让它理解 IPV4 地址?
到此为止。
更新
按照 Takao 的建议,更改
$connection.send($counter)
到
$connection.send($counter.Str)
解决了问题(虽然我在另一个程序上尝试过,不是这个)。
让我们一步步解决这个问题。
首先,你的代码在我看来是正确的,除了一些小的地方。
当我复制你的代码时,它确实不起作用,所以我用cro trace .
而不是cro run .
试了一下。您可以在 official docs 中找到有关该模式的信息。
另一种方法是设置 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
创建的默认服务器)也会为每条传入消息发送回复,因此您的示例会无休止地发送消息。为了防止你可以考虑添加一个条件,在这种情况下你将不再发送东西,但是好吧,这无论如何是一个测试示例,所以由你决定。
关于您的其他问题:
Another question, shoudn't "$connection.send" return a Promise or something?
应该不会吧,接下来我会把cro的架构细节写出来解释一下。正如您可能通过阅读 docs 了解到的那样,cro 管道基本上只是一堆 Cro::Transform
包装的供应品。在 Cro::Websocket::Client::Connection
内部,send
方法只是将一个东西直接发送到整个管道的 Cro::Source
中,简单的 $supplier.emit($message)
你不会出错(这个方法的真正实现看起来非常接近这条线)。您遇到的事情发生在管道的更深处。我确信隐藏这种情况的异常不是一个好的用户体验,所以我会考虑制作一个补丁来传播异常,这样它会更容易捕获(尽管你总是可以使用调试模式)。
it seems the server only understands IPV6 addresses...how to make it understand IPV4 addresses ?
我不太确定,请打开一个新问题。