This is about one of those projects where you have to dig into some new cool technology and wonder what the buzz is about. ZeroMQ and all its flavors is about using queueing and web sockets to create pubsub integrations with, in my case, NetMQ as a service and a browser as a client (using jsMQ). Really pleasantly surprised how easy it is to push data to the browser and even ‘stream’ images to subscribers.

On the server an MQ service publishes a stream of images like so

 

 using (var context = NetMQContext.Create())
            {
                using (WSRouter router = context.CreateWSRouter())
                using (WSPublisher publisher = context.CreateWSPublisher())
                {
                    router.Bind("ws://localhost:80");
                    publisher.Bind("ws://localhost:81");

                    router.ReceiveReady += (sender, eventArgs) =>
                    {
                        var identity = eventArgs.WSSocket.Receive();

                        var message = eventArgs.WSSocket.ReceiveString();
                        Console.WriteLine(message);
                        // let the webbrowser know we got the message
                        eventArgs.WSSocket.SendMore(identity).Send("OK");

                       if (message == "stream")
                        {
                            for (var i = 1; i < 1000; i++)
                            {
                                publisher.SendMore("stream").Send(Imaging.GetMachineImage(2, i));
                            }
                        }
                    };

                    var poller = new Poller();
                    poller.AddSocket(router);

                    poller.Start();

                }
            }

Can’t get much easier than that, does it? A poller listens to subscribers and if it asked for a stream we start streaming images. In fact, you could create a Netflix-like system in this way if you wished.

On the client, you need to hook up the jsMQ lib and some JavaScript queueing system to buffer the incoming images from the published. Once the buffer has sufficient images you start playing the images by dequeueing them via a simple setInterval method, which mimics the frame-per-second process.

 

 dealer = new JSMQ.Dealer();
        dealer.connect("ws://localhost");
        // we must wait for the dealer to be connected before we can send messages, any messages we are trying to send
        // while the dealer is not connected will be dropped
        dealer.sendReady = function () {
            requestLatest();
        };
        subscriber = new JSMQ.Subscriber();
        subscriber.connect("ws://localhost:81");
        subscriber.subscribe("latest");
        subscriber.subscribe("stream");
        subscriber.onMessage = function (message) {
 
            var topic = message.popString();
            if (topic === "stream")  {
                var data = message.popBuffer();
                streamBuffer.enqueue(base64ArrayBuffer(data));
                if (streamBuffer.getLength() > 20 && !isPlaying) {
                    startPlaying();
                }
            }
        };


 function startPlaying() {
        if (isPlaying) return;
        isPlaying = true;
       
        var showOne = function () {
            if (streamBuffer.isEmpty()) {
                stopPlaying();
            }
            document.getElementById("viewer").src = "data:image/png;base64," + streamBuffer.dequeue();
        }
        player = setInterval(showOne, 800);

    }

Ain’t it astonishing in its simplicity? For sure it would have been a whole lot more complex to use WCF or similar to achieve the same result. So, yes, I’ve become a fan of ZeroMQ and web sockets. Great fun.