首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >关闭连接到Mojo websocket的Mojo::IO循环循环事件

关闭连接到Mojo websocket的Mojo::IO循环循环事件
EN

Stack Overflow用户
提问于 2016-04-17 06:16:41
回答 2查看 911关注 0票数 8

我在和莫灼利和韦伯索克斯一起玩。我想将服务器上多个外部命令的输出发送到网页。我在连接和接收消息方面没有问题,但我也希望向服务器发送一条消息,以停止外部命令,同时让其他命令继续向客户端发送消息。我还想在外部命令退出后停止检查它。

外部命令只是一个一行,每隔几秒钟就会发出一个整数。我有两个websocket,它在不同的div中显示数字。单击任何一个停止按钮都会发送消息,但这是我需要知道如何关闭websocket(只有websocket)并关闭外部命令的地方。

连接websocket时,运行外部命令并设置一个Mojo::IOLoop->recurring以检查是否有输出。

当我想要停止时,我想我应该调用Mojo::IOLoop->remove($id),但这似乎并没有完全删除它,我得到了像Mojo::Reactor::Poll: Timer failed: Can't call method "is_websocket" on an undefined value这样的错误消息。

如果我在控制器对象上调用finish来关闭websocket,它似乎会停止一切。

我有整个gist::Lite应用程序作为一个要点,但这是我

代码语言:javascript
复制
use feature qw(signatures);
no warnings qw(experimental::signatures);
## other boilerplate redacted

websocket '/find' => sub ( $c ) {
    state $loop = Mojo::IOLoop->singleton;

    app->log->debug( "websocket for find" );
    $c->inactivity_timeout( 50 );

    my $id;
    $c->on( message => sub ( $ws, $message ) {
        my $json = decode_json( $message );
        my $command = $json->{c};
        my $name    = $json->{n};

        app->log->debug( "Got $command command for $name" );
        if( $command eq "start" ) {
            $id = run_command( $ws );
            app->log->debug( "run_command for $name returned [$id]" );
            }
        elsif( $command eq "stop" ) {
            app->log->debug( "stopping loop for $name [$id]" );
            # XXX What should I do here?
            # $ws->finish;
            # $loop->remove( $id );
            }
        elsif( $command eq "open" ) {
            app->log->debug( "opening websocket for $name" );
            }
        }
        );
     $c->on(
        finish => sub ( $c, $code ) {
            app->log->debug("WebSocket closed with status $code");
            }
        );
    };

app->start;

sub run_command ( $ws ) {
    app->log->debug( "In run_command: $ws" );
    open my $fh, "$^X -le '\$|++; while(1) { print int rand(100); sleep 3 }' |";
    $fh->autoflush;

    my $id;
    $id = Mojo::IOLoop->recurring( 1 => sub ($loop) {
        my $m = <$fh>;
        unless( defined $m ) {
            app->log->debug( "Closing down recurring loop from the inside [$id]" );
            # XXX: what should I do here?
            close $fh;
            return;
            };
        chomp $m;
        app->log->debug( "Input [$m] for [$id] from $fh" );
        $ws->send( encode_json( { 'm' => $m } ) );
        });

    return $id;
    }

可能从这一答案中受益的其他问题:

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-22 01:50:07

我玩了一会儿这个。洛吉奥尼茨的回答让我觉得我不应该亲自轮询或处理文件处理细节。我还是不知道它挂在哪里。

相反,我使用Mojo::反应堆io来设置一个文件句柄来监视:

代码语言:javascript
复制
sub run_command ( $ws ) {
    my $pid = open my $fh, "$^X -le '\$|++; print \$\$; while(1) { print int rand(100); sleep 3 }' |";
    $fh->autoflush;

    my $reactor = Mojo::IOLoop->singleton->reactor->io(
        $fh => sub ($reactor, $writeable) {
            my $m = <$fh>;
            chomp $m;
            $ws->send( encode_json( { 'm' => $m } ) );
            }
        );

    return ( $fh, $pid );
    }

当我完成该命令时,我可以取消该文件句柄并终止该进程。我完成了websocket:

代码语言:javascript
复制
    elsif( $command eq "stop" ) {
        $loop->reactor->watch( $fh, 0, 0 );
        kill 'KILL', $pid or app->log->debug( "Could not kill $pid: $!" );
        $ws->finish;
        }

我还是不知道为什么remove($fh)不工作。我想我泄露了一些IOLoop的东西,就是这样做的。

票数 2
EN

Stack Overflow用户

发布于 2016-04-18 11:12:28

我认为您阻塞事件循环,因为您的重复调用每秒钟和my $m = <$fh>;等待结果约2-3秒。所以你阻止了事件循环。我认为是这样的,因为当我运行您的应用程序时,事件finish不是调用非活动超时,而是调用事件recurrentfinish事件必须始终调用非活动超时。

我认为您的代码必须处于单独的进程中,以避免阻塞事件循环。

尝试使用模块在单独的进程中执行。I 小例子。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36673303

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档