I have a pretty simple use case where I want a websocket (or something like it) to send the contents of ZMQ pub/sub messages out to a browser in real time for an indefinite period of time. It's for personal use (home automation) so doesn't need to scale too much, but does need to be robust.

One-way communication (server to browser) is fine, but two ways would be nice, I guess. Not worried about two-way right now, since I can easily use HTTP(s) for browser-to-server.

I would like to use Mojolicious:: Lite (or something I can easily run in hypnotoad, and which allows for in-script hypnotoad configuration).

I found examples that look like they should work, but for me they don't - once the code hits the IO loop (whether the Mojo one or AnyEvent) to receive subscribed messages, I get either an 'operation on closed socket' if I'm using ZMQ::FFI, or a more cryptic error (something like Assertion failed: pfd.revents & POLLIN) if I use the ZMQ library like in the examples.

I decided to take a break and write the code in a plain perl script with Net::WebSocket::Server and AnyEvent, and found that it works fine when run from the command line:

use strict; use IO::Socket::SSL; use ZMQ::FFI; use ZMQ::FFI::Constants qw (ZMQ_SUB); use AnyEvent; use EV; my $wsport = '3000'; my $zmqhost = 'tcp://localhost:5555'; my $subject = 'event'; Net::WebSocket::Server->new( listen => $wsport; on_connect => sub { my ($serv, $conn) = @_; $conn->on( ready => sub { my $context = ZMQ::FFI->new(); my $subsocket = $context->socket(ZMQ_SUB); $subsocket->connect($zmqhost); $subsocket->subscribe($subject); my $fd = $subsocket->get_fd(); my $w = AE::io $fd, 0, sub { while ($subsocket->has_pollin) { $conn->send_utf8($subsocket->recv()); } }; EV::run(); }, ); }, )->start;
which makes me think I should easily be able to make it work in Mojolicious::Lite, but for the life of me I can't seem to do it. It might be that in the code above, I'm able to put a subroutine in the on 'ready' state, but I can't figure out how to do that in the Mojolicious::Lite world.

(I would just use that code above, but it's single-user and not at all fault tolerant, and I'd rather not write a bunch of code to solve those issues if I don't have to)

Anyone with a suggestion on how to get this working in Mojolicious / hypnotoad, or perhaps another approach?


In reply to Mojolicious websocket question by antichef

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.