使用 Amp\Websocket 从打开的流连接中获取 websocket ping?

Posted

技术标签:

【中文标题】使用 Amp\\Websocket 从打开的流连接中获取 websocket ping?【英文标题】:Get websocket pings from an open stream connection using Amp\Websocket?使用 Amp\Websocket 从打开的流连接中获取 websocket ping? 【发布时间】:2020-03-20 19:40:02 【问题描述】:

我在这里使用自述文件示例:

https://github.com/amphp/websocket-client/blob/master/README.md

use Amp\Websocket;
use Amp\Delayed;
use Amp\Websocket\Connection;
use Amp\Websocket\Handshake;
use Amp\Websocket\Message;
use function Amp\Websocket\connect;

\Amp\Loop::run(function () use ($fn)

    try 
    
        $connection = yield connect('wss://....');

        yield $connection->send('
            "action":"authenticate",
            "data":
                ...
            
        ');
                
        while ($message = yield $connection->receive()) 
        
            $payload = yield $message->buffer();

            // print the payload
            $this->info($payload);  

            // custom function to parse the payload
            $r = $fn($payload);

            if ($r == false) 
                $this->warn('Connection closed.');
                $connection->close();
                break;
            
        
    
    catch (\Throwable $e) 
        $this->isError($e->getMessage(),true);
    
    catch (\Exception $e) 
        $this->isError($e->getMessage(),true);
    
);

问题: while 循环只会在通过流发送消息时运行,没有消息,任何事情都不会发生,因为它处于空闲模式等待。

解决方案: 如何接收 ping 或在 ping 上运行 while 循环,并仍然收集消息?

例如,我想控制检查一些信息,(例如套接字应该保持打开)但是,它只能检查当消息通过流时,这会限制脚本,因为它只会在有活动时执行,因此如果没有发送任何信息,则永远等待。

Ping 是基于 RFC 的 Web 套接字中的标准:https://www.rfc-editor.org/rfc/rfc6455

Rfc6455Connection 连接类中,有 ping,但没有关于如何访问或直接使用它的文档。

在 ping 上运行 while 循环并同时检查是否有消息会很酷,这可能吗?

【问题讨论】:

已在 GitHub 上回答:github.com/amphp/websocket-client/issues/23 【参考方案1】:

amphp/websocket-client 自动处理 ping 并响应它们,因此接收消息是 API 用户应该关心的唯一问题。

使用 Amp,您可以随时使用 Amp\call / Amp\asyncCall 生成多个协程,例如在空闲一段时间后关闭连接。

Loop::run(function () 
    try 
      $connection = yield connect($uri);

      asyncCall(function () use ($connection) 
        while (true) 
          if (!$this->isActive()) 
            $connection->close();
            break;
          

          yield Amp\delay(1000);
        
      );

      yield $connection->send('...');

      while ($message = yield $connection->receive()) 
          $payload = yield $message->buffer();

          $r = $fn($payload);

          if ($r == false) 
              $this->warn('Connection closed.');
              $connection->close();
              break;
          
      
   catch (\Exception $e) 
      $this->isError($e->getMessage(),false);
  
);

【讨论】:

感谢您对 Github 问题的帮助,我先发布了这个问题,但您已经给了我所需的答案。再次感谢。

以上是关于使用 Amp\Websocket 从打开的流连接中获取 websocket ping?的主要内容,如果未能解决你的问题,请参考以下文章

从不可搜索的流中打开 System.IO.Packaging.Package

imap_open : 无法打开到我的邮件服务器的流

如何使用 Amphp 捕获 php websocket 断开的 TCP 连接异常?

GUN C中的流

如何从 .NET 中的流中获取 MemoryStream?

如何使用 C++ 中的流从文件末尾读取给定数量的行?