You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义主循环中Net::Async::WebSocket::Server连接失败求助

自定义主循环下Net::Async::WebSocket::Server无法建立连接的问题

我希望实现一个由自定义主循环而非IO::Async::Loop控制的WebSocket服务器,代码如下:

my $sslSocket = IO::Socket::SSL->new(
    Listen             => 5,
    LocalPort          => XXX,
    Proto              => 'tcp',
    SSL_startHandshake => 0,
    SSL_cert_file      => 'XXX',
    SSL_key_file       => 'XXX',
) or die "failed to listen: $!";

my $server = Net::Async::WebSocket::Server->new(
    on_client => sub {
        my ( undef, $client ) = @_;

        $client->configure(
            on_text_frame => sub {
                my ( $self, $frame ) = @_;

                $self->send_text_frame( $frame );
            },
        );
    },
    on_handshake => sub {
        my ( $self, $client, $hs, $continue ) = @_;

        $continue->( 1 );
    }
);

my $loop = IO::Async::Loop->new;
$loop->add( $server );

$server->listen(
    handle => $sslSocket
)->get;

我在自定义主循环中,仅当监听套接字$sslSocket有数据可读时才调用$loop->loop_once,代码如下:

while(1){
  # something before
  if (//data to read) {
    $loop->loop_once;
  }
  # something after
}

但WebSocket连接始终无法建立,所有回调函数都未被触发。我猜测自己误解了loop_once的用途,但不清楚具体问题所在。我尝试过使用$loop->run方法,此时连接可以正常建立,但这不符合我的需求。期望实现的效果是:调用loop_once时,WebSocket服务器能处理待处理的请求。


问题原因

你的自定义循环只关注监听套接字$sslSocket的可读事件,但WebSocket连接的建立过程远不止这一步:

  1. 客户端发起TCP连接后,会生成新的客户端套接字;
  2. 后续需要完成SSL握手、HTTP升级到WebSocket的握手流程;
  3. 这些步骤都依赖新客户端套接字的读写事件,而你的循环完全没处理这些事件,导致握手流程卡壳,回调自然不会触发。

loop_once的作用是处理当前loop中所有已就绪的事件,但前提是你得让loop知道哪些事件已经就绪——而你只给了它监听套接字的事件,漏掉了其他关键事件。

解决办法

不要手动判断单个套接字的状态,而是让IO::Async::Loop自己管理所有需要监听的文件描述符,修改自定义循环如下:

while (1) {
    # something before

    # 获取当前loop需要监听的所有文件描述符集合
    my ( $read_fds, $write_fds, $except_fds ) = $loop->pre_wait;

    # 等待事件发生,这里设置0.1秒超时(可根据需求调整)
    my $nfound = select( $read_fds, $write_fds, $except_fds, 0.1 );

    if ($nfound > 0) {
        # 处理所有已就绪的事件
        $loop->loop_once;
    }

    # something after
}

关键说明

  • $loop->pre_wait:返回当前loop中所有注册的文件描述符(包括监听套接字、已建立的客户端套接字等)的读、写、异常事件集合;
  • select:等待这些集合中的任意事件发生,确保不会漏掉任何关键步骤;
  • 只有当有事件就绪时调用loop_once,既满足自定义循环的控制权需求,又能让WebSocket服务器完整处理连接建立和消息交互的所有流程。

内容的提问来源于stack exchange,提问作者Talkabout

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 20:50:28