当前位置: 首页 > 知识库问答 >
问题:

Cro WebSocket客户端看不到服务器何时出去

曾飞沉
2023-03-14

下面的客户端程序从WebSocket服务器接收消息。
它不发送任何消息。

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

constant WS-URL = 'ws://localhost:20000/status';
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
{
  my $cause = $connection-attempt.cause;
  say '"* error when trying to connect to server';
  say '"* --------------------------------------';
  # $cause is a long string, how do we get a simple numeric code ?
  say $cause;
  say '"* ======================================';
  exit 1;
}

my $connection = $connection-attempt.result;
my $peer = 'localhost:20000';
say '* connected with ', $peer;

react
{
  whenever $connection.messages -> $message
  {
    my $body = await $message.body;
    say '* received message=[' ~ $body ~ '] from server';
    LAST { say '* LAST'; done; }
    QUIT { default { say '* QUIT'; done; }}
  }
  CLOSE { say '* CLOSE: leaving react block';}
} # react
use Cro::HTTP::Router;
use Cro::HTTP::Server;
use Cro::HTTP::Router::WebSocket;

my $application =
route
{
  get -> 'status'
  {
    web-socket -> $incoming
    {
      my $counter = 0;
      my $timer = Supply.interval(1);

      supply
      {
        whenever $incoming -> $thing
        {
          LAST { note '* LAST: client connection was closed'; done; }
          QUIT { default { note '* QUIT: error in client connection'; done;  } }
        }
        whenever $timer
        {
          $counter++;
          say '* sending message ', $counter;
          emit $counter.Str;
        }
        CLOSE { say '* CLOSE: leaving supply block'; }
      } # supply
    } #incoming
  } # get -> status
}

my $server = Cro::HTTP::Server.new: :port(20000), :$application;

$server.start;

say '* serving on port 20000';

react whenever signal(SIGINT)
{
  $server.stop;
  exit;
}

现在,当服务器退出时(比如说,通过Ctrl C),客户机什么也看不到。

在客户机中设置CRO_TRACE=1会产生以下结果:

TRACE(anon 2)] Cro::WebSocket::MessageParser EMIT WebSocket Message - Text

* received message=[4] from server
[TRACE(anon 1)] Cro::TCP::Connector DONE
[TRACE(anon 2)] Cro::WebSocket::FrameParser DONE
[TRACE(anon 2)] Cro::WebSocket::MessageParser DONE
[TRACE(anon 1)] Cro::HTTP::ResponseParser DONE
^C  

客户没有显示更多内容(然后我取消了它)。

所以,问题是:客户机应该如何处理这种情况?

编辑了问题,现在显示服务器代码
还有,我在Fedora 28。当我第一次取消服务器时,netstat显示

$ netstat -ant | grep 20000
tcp6       0      0 ::1:20000               ::1:56652               TIME_WAIT  
$

Tcpdump显示

IP6 ::1.20000 > ::1.56652: Flags [F.], seq 145, ack 194, win 350, options [nop,nop,TS val 1476681452 ecr 1476680552], length 0
IP6 ::1.56652 > ::1.20000: Flags [F.], seq 194, ack 146, win 350, options [nop,nop,TS val 1476681453 ecr 1476681452], length 0
IP6 ::1.20000 > ::1.56652: Flags [.], ack 195, win 350, options [nop,nop,TS val 1476681453 ecr 1476681453], length 0

从客户端到服务器的最后一次确认似乎丢失了,我猜客户端没有关闭连接。

此外,我很好奇为什么Cro选择默认使用IPv6。

共有1个答案

孙成益
2023-03-14

这是一个自发布此问题以来已修复的错误,但我留下一个答案,因为这部分问题可能会让人们在处理Raku的网络时感到困惑:

此外,我很好奇为什么Cro选择默认使用IPv6。

localhost将首先解析到IPv6地址,如果这是主机文件中localhost的第一个地址。在撰写本文时,IO::Socket::Async(Cro内部使用)只允许将PF_UNSPEC指定为一个系列,并且是从主机名解析结果中使用的唯一地址是收到地址列表中的第一个。这将在将来的某个时候改变,作为我的IP6NS授权工作的一部分,也是一个解决问题的问题,以改善DNS的处理方式,但是现在,如果你想只使用IPv4/IPv6,你应该指定127.0.0.1/::1而不是使用localhost(或者如果它们不同,您的机器将其解析到的任何地址)。

 类似资料:
  • 我想在一些计算机之间建立点对点连接,这样用户就可以在没有外部服务器的情况下聊天和交换文件。我最初的想法如下: 我在服务器上制作了一个中央服务器插座,所有应用程序都可以连接到该插座。此ServerSocket跟踪已连接的套接字(客户端),并将新连接的客户端的IP和端口提供给所有其他客户端。每个客户端都会创建一个新的ServerSocket,所有客户端都可以连接到它。 换句话说:每个客户端都有一个Se

  • 我正在创建我的产品,并与这个问题。有一天,我设置了Socket.io,一切都很好。第二天,我将服务器和客户端从http迁移到HTTPS。迁移后客户端和服务器端仍然连接,但不能从客户端发射到服务器,从服务器发射到客户端。 我的ssl证书位于和中,它们加载正确。运行在上的服务器 我的示例react组件。我的react应用程序运行在上。HTTPS连接良好,工作良好。 我该怎么办?也许我在中错误地使用了s

  • 我有一个客户端服务器的情况,每一方都在测量时间,但似乎有一个问题,即测量的时间不匹配。长话短说,这个想法是有一个倒计时,之后程序需要做事情。我在服务器端测量这个。但是,倒计时需要显示,所以我所做的是在客户端单独运行它。最终结果是,当服务器发送消息时,客户端显示为23秒,该消息表明时间倒计时为10分钟。 客户端为XNA,代码: 然后从可用时间中减去计时器,并显示出来。在服务器端,这种情况正在发生:

  • 我正在尝试使用hazelcast v3。2.4(服务器和客户端上的版本相同)。服务器(我可以安装的简单实现)正在服务器上运行。客户端尝试连接到远程服务器-服务器打印身份验证请求,但我收到以下日志输出(包括异常)-关于我可以做什么不同的想法(复制日志输出和配置文件)。我正在尝试通过TCP/IP进行连接,我检查了网络连接——我没有看到任何东西阻止连接。 堆栈中提到的代码行: 配置 日志输出 服务器输出

  • 前面的章节介绍了所有 Redis 的重要功能组件: 数据结构、数据类型、事务、Lua 环境、事件处理、数据库、持久化, 等等, 但是我们还没有对 Redis 服务器本身做任何介绍。 不过, 服务器本身并没有多少需要介绍的新东西, 因为服务器除了维持服务器状态之外, 最重要的就是将前面介绍过的各个功能模块组合起来, 而这些功能模块在前面的章节里已经介绍过了, 所以本章将焦点放在服务器的初始化过程,