4

私は Perl の初心者で、現在 websocket と戦っています。たくさん読んで、試して、コピーして貼り付けた後、次のコードが機能するようになりました。

use strict;
use warnings;
use utf8;
use Data::Dumper;
use IO::Async::Loop;
use IO::Async::Timer::Periodic;
use Net::Async::WebSocket::Client;
use Protocol::WebSocket::URL;

my ($url, $msg, $last_update);
$url  = 'ws://127.0.0.1/stream';
$msg  = 'get_lists';

my $uri = Protocol::WebSocket::URL->new->parse($url);
my $loop = IO::Async::Loop->new;
my $client = Net::Async::WebSocket::Client->new(
        on_frame => sub {
                my ($self, $frame) = @_; 
                chomp($frame);
                $last_update = time(); # use this in timer below

                # do something else
        }   
);
$loop->add($client);

$client->connect(
        host    => $uri->host, 
        service => $uri->port, 
        url     => $url, 
        on_connected => sub {
                warn "Connection established";

                if ($msg) {
                        $client->send_frame("$msg\n");
                }   
        },  
        on_connect_error=> sub { die "CONNECT: ".Dumper \@_; },
        on_resolve_error=> sub { die "RESOLVE: ".Dumper \@_; },
        on_fail         => sub { die "FAIL: ".Dumper \@_; },
        on_read_eof     => sub {
                $loop->remove($client);

                # reconnect?
        }   
);

# is the connection to socket is still open?
# check every 30 seconds if $last_update was not updated
my $timer = IO::Async::Timer::Periodic->new(
        interval=> 30,
        on_tick => sub {
                if (!$last_update || time()-30 > $last_update) {
                        warn "Connection probably dead. No new data for 20 seconds.";

                        ## check connection

                        ## and reconnect if needed
                }
        },
);
$timer->start;
$loop->add($timer);

$loop->loop_forever;

ここでもう 1 つ必要なのですが、これを解決する方法がわかりません。

https://stackoverflow.com/a/12091867/1645170のような情報を見つけましたが、コードに SO_KEEPALIVE を配置する方法がわかりません。おそらく独自の IO::Socket 接続を作成し、それを Async::Net::WebSocket に渡す必要がありますが、できませんでした。実際、私はこれをどのように行うべきか本当にわかりません。明らかに初心者の問題。

接続が開いているかどうかを30秒ごとにチェックするタイマーを使用して2番目のアプローチを試しました(新しいデータがソケットから来ていない場合)。繰り返しますが、同じ問題ですが、反対側から: 上記のコードで接続が開いているかどうかを確認する方法がわかりません。

基本的な IO::Socket 接続を作成できますが、Net::Async::WebSocket がイベント (on_read-eof、on_frame など) でそれを行う方法が好きなので、上記のコードで何とかしたいと思います。

4

1 に答える 1

1

それがまだ機能しているかどうかを確認する方法は?

「ハートビート」を作成します。クライアントから x 秒ごとに「ping」を送信し、「pong」が返されるまで待ちます。タイムアウトになると死ぬ。

サーバーでは、独自のソケットを追加できます (例の 1 つから)。

それがあなたを助けることを願っています。

my $serversock = IO::Socket::INET->new(
   LocalHost => "127.0.0.1",
   Listen => 1,
) or die "Cannot allocate listening socket - $@";

$serversock->setsockopt(SOL_SOCKET, SO_KEEPALIVE, 1);

my @serverframes;

my $acceptedclient;
my $server = Net::Async::WebSocket::Server->new(
   handle => $serversock,
于 2012-09-04T12:33:19.860 に答える