bridging the worlds with ØMQ

I wanted to play with ØMQ since @ph_j got me excited about it on the DWX15 last week.

This is the result after a rainy lunch-break: Just a quick post on how I got ØMQ working on Windows with Haskell and .net/C# 😉

Install / Windows

First I grabbed the installer for my 64-bit windows and ran it.

Next I had to rename a few files (see below):

  • in /bin I opted for libzmq-v120-mt-4_0_4.dll, copied it to zmq.dll and copied it in to my \System32 folder
  • in /lib copied the .lib with the same name (libzmq-v12-mt-4_0_4.lib) to zmq.lib

Haskell

In a project with a dependency to zeromq4-haskell >= 0.1 I had the problem that cabal install --dependencies-only (in a sandbox) failed with

* Missing C library: zmq

that is why I copied the files from above. I finally managed to install the package with:

cabal install 
    --dependencies-only 
    --extra-include-dirs="[PathToZeroMQ]/include" 
    --extra-lib-dirs="[PathToZeroMQ]/lib"

after this the basic source-code from the ZGuide

-- |
-- Hello World server in Haskell
-- Binds REP socket to tcp://*:5555
-- Expects "Hello" from client, replies with "World"

module Main where

import System.ZMQ4.Monadic
import Control.Monad (forever)
import Data.ByteString.Char8 (pack, unpack)
import Control.Concurrent (threadDelay)

main :: IO ()
main =
    runZMQ $ do  
        liftIO $ putStrLn "Starting Hello World server"
        repSocket <- socket Rep
        bind repSocket "tcp://*:5555"
  
        forever $ do
            msg <- receive repSocket
            liftIO . putStrLn $ unwords 
                ["Received request:", unpack msg]

            -- Simulate doing some 'work' for 1 second
            liftIO . threadDelay $ 1 * 1000 * 1000

            send repSocket [] (pack "World")

works as it is (of course it does not shut down gracefully).

CSharp

For the C#-Client I first installed the clrzmq-x64-nuget (although I am not to sure if this is the right one, it might be outdated – but it works).

Here I had to rewrite the example-code a bit:

const string endpoint = "tcp://127.0.0.1:5555";

// Create
using (var context = new Context())
using (var requester = context.Socket(SocketType.REQ))
{
    // Connect
    requester.Connect(endpoint);

    for (var n = 0; n < 10; ++n)
    {
        const string requestText = "Hello";
        Console.Write("Sending {0}…", requestText);

        // Send
        requester.Send(requestText, Encoding.UTF8);

        // Receive
        var reply = requester.Recv(Encoding.UTF8);
        Console.WriteLine(" Received: {0} {1}!", 
                            requestText, reply);
    }
}

But the original one (that used the ZeroMQ nuget) had some runtime problems with finding a library and I think this one just uses the same as Haskell.

Result

ZeroMQ in Action

ZeroMQ in Action