我可以通过Web套接字动态更新HTML吗?

时间:2017-04-01 03:43:38

标签: perl websocket

我是网络套接字的新手,我正在围绕与物联网设备对话的命令行界面构建一个Web GUI。有些命令需要几秒钟才能运行,因为我将它们发送到大型设备网络。

如果响应进来,我可以将单个设备响应传递给textarea(类似于终端窗口),这将非常有用。

我正在使用客户端和服务器之间的Web套接字连接。这是我想要实现的效果的简化示例。

#!/usr/bin/env perl

use strict;
use warnings;
use Mojolicious::Lite;

get '/' => 'index';

websocket '/get_loop' => sub {

    my $c = shift;

    $c->app->log->debug("Websocket opened");

    $c->on(message => sub {

        my ($c, $msg) = @_;

        for (my $i = 0; $i < 10; $i++) {
            $c->send("$i\n");
            $c->app->log->debug("$i\n");
            sleep (1);
        };
    });

    $c->on(finish => sub {
        my ($c, $code, $reason) = @_;
        $c->app->log->debug("WebSocket closed with status $code");
    });
};

app->start;

__DATA__

@@ index.html.ep
<html>
<head>
    <title>Websocket Test</title>
    <style type="text/css">
        textarea {
            height: 200px;
            width: 100px;
        }
    </style>
</head>
<body>
    <h1>Websocket Test</h1>
    <textarea id="terminal" readonly></textarea>
    <script type="text/javascript">
        var ws = new WebSocket('ws://127.0.0.1:3000/get_loop');
        var terminal = document.getElementById('terminal');
        ws.onopen = function() {
            ws.send('start');
        };
        ws.onmessage = function(event) {
            var msg = event.data;
            terminal.innerHTML += msg;
        };
    </script>
</body>
</html>

在这个例子中,我有一个从0到14的循环计数。我正在尝试通过Web套接字将每个计数发送到textarea,以便在循环计数时显示。循环模拟我实际应用程序中的CLI响应。这甚至可以在网络套接字上进行吗?

- 编辑 -

修改上述Web套接字代码并使用Mojo::IOLoop->recurring解决问题而无需求助于多线程。

websocket '/get_loop' => sub {

    my $c = shift;

    $c->app->log->debug("Websocket opened");

    my $id;
    $c->on(message => sub {

        my ($c, $msg) = @_;

        my $count = 0;
        $id = Mojo::IOLoop->recurring(1 => sub {
            $c->send("$count\n");
            $c->app->log->debug($count);
            sleep (1);
            $c->finish if $count++ == 10;
        });
    });

    $c->on(finish => sub {
        my ($c, $code, $reason) = @_;
        Mojo::IOLoop->remove($id);
        $c->app->log->debug("WebSocket closed with status $code");
    });
};

1 个答案:

答案 0 :(得分:0)

您需要在页面上创建javascript websocket侦听器并插入传递到DOM中的数据。

const socket = new WebSocket('ws://localhost:8080');
socket.addEventListener('open', function (event) {
    socket.send('Hello Server!');
});

socket.addEventListener('message', function (event) {
    var div = document.getElementById('divID');
    div.innerHTML = event.data;
});

哦,我明白了,你的问题是关于服务器的Perl代码。我建议在Perl中创建一个静态连接数组,在open事件上分配它们,在close事件中取消它们。您不需要在on message sub中重新发送数据。您可以使用Event :: Lib $ event-&gt; add([$ timeout])然后枚举打开的套接字(到各种不同的Web客户端)调用$ c-&gt; send(“$ i \ n”);它完全是异步的,因此无需将其与on message sub绑定。服务器可以随时执行。

在PERL中创建静态变量: http://www.perlmonks.org/?node_id=8299