Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I send periodic messages to connected clients of a Websocket in Perl

This question is similar to this one for Python: WebSocket Server sending messages periodically in python

The example given for creating a WebSocket in Perl uses a small message sending service: http://search.cpan.org/~topaz/Net-WebSocket-Server-0.001003/lib/Net/WebSocket/Server.pm

The code is:

use Net::WebSocket::Server;

my $origin = 'http://example.com';

Net::WebSocket::Server->new(
    listen => 8080,
    on_connect => sub {
        my ($serv, $conn) = @_;
        $conn->on(
            handshake => sub {
                my ($conn, $handshake) = @_;
                $conn->disconnect() unless $handshake->req->origin eq $origin;
            },
            utf8 => sub {
                my ($conn, $msg) = @_;
                $_->send_utf8($msg) for $conn->server->connections;
            },
            binary => sub {
                my ($conn, $msg) = @_;
                $_->send_binary($msg) for $conn->server->connections;
            },
        );
    },
)->start;

This example is event based and only sends messages to clients based on messages sent from clients. If I wanted to send a periodic message to all connected clients, what is a good way of doing that? Can I create a periodic event that triggers within the socket server, or is there a way to create a Perl client that connects to the server and sends messages, which the server then broadcasts out?

like image 446
Vijay Boyapati Avatar asked Oct 20 '22 03:10

Vijay Boyapati


2 Answers

Upgrade to Net::WebSocket::Server v0.3.0, which has this functionality built-in via its "tick_period" parameter and "tick" event. See example below:

use Net::WebSocket::Server;

my $ws = Net::WebSocket::Server->new(
    listen => 8080,
    tick_period => 1,
    on_tick => sub {
        my ($serv) = @_;
        $_->send_utf8(time) for $serv->connections;
    },
)->start;
like image 121
Topaz Avatar answered Oct 23 '22 03:10

Topaz


I found a simple workaround, although I'm not sure if it's the best solution. One of the events that can be triggered by the Websocket server is on_pong. Furthermore, if you set silence_max when creating the Websocket server, it periodically pings all clients, waiting for a pong response. This pong can then be used to trigger a message to all clients. Code below:

my $server = Net::WebSocket::Server->new(
    listen => 2222,
    silence_max => 5, # Send a ping to cause a client pong ever 5 seconds
    on_connect => sub {
    my ($serv, $conn) = @_;
    $conn->on(
        handshake => sub {
            my ($conn, $handshake) = @_;
            print $handshake->req->origin."\n";
            $conn->disconnect() unless $handshake->req->origin eq $origin;
        },
        utf8 => sub {
            my ($conn, $msg) = @_;
            my $num_connections = scalar $conn->server->connections;
            foreach my $connection ($conn->server->connections) {
                if ($conn != $connection) {
                    $connection->send_utf8("$num_connections connected: ".$msg);
                }
            }
        },
        pong => sub {
            foreach my $connection ($conn->server->connections) {
                $connection->send_utf8("Broadcast message!!");
            }
        },

            );
    },
    );
like image 37
Vijay Boyapati Avatar answered Oct 23 '22 04:10

Vijay Boyapati