Search code examples
c#zeromqnetmq

Correct pattern for ZeroMQ Server/Client type


I have a server that needs to get instructions to run processes for clients on another machine.

The clients send a job message, the Server processes the job and later sends the back results.

I tried using the NetMQ Request-Response pattern (see below)

This works nicely for 1 client, BUT if a second client sends a request before previous client job is finished - I get an error.

I really need to be able to receive ad-hoc messages from clients, and send results when they are completed. Clearly, I am using the wrong pattern, but reading the ZeroMQ docs has not highlighted a more appropriate one.

namespace Utils.ServerMQ
{
    class ServerMQ
    {
        public static void Go()
        {
            using (var responseSocket = new ResponseSocket("@tcp://*:393"))
            {
                while (true)
                {
                    Console.WriteLine("Server waiting");
                    var message = responseSocket.ReceiveFrameString();

                    Console.WriteLine("Server Received '{0}'", message);

                    //System.Threading.Thread.Sleep(1000);
                    var t2 = Task.Factory.StartNew(() =>
                    {
                        RunProcMatrix(message, responseSocket);
                    });

                }
            }
        }

        public static void RunProcMatrix(object state, ResponseSocket responseSocket)
        {
            var process = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName = Path.Combine(@"H:\Projects\Matrix\Matrix\bin\Debug\", "Matrix001.exe"),
                    Arguments = (string)state,
                    WindowStyle = ProcessWindowStyle.Normal,
                    CreateNoWindow = false
                }
            };
            process.Start();
            process.WaitForExit();


            responseSocket.SendFrame((string)state);
        }
    }
}

Solution

  • You want a ROUTER socket on the server side, so it can receive multiple requests at a time. (Guide) REQ sockets on the client side are still fine unless the server may arbitrarily push data to them, then they need to be DEALER sockets.

    Note that for sockets beyond REQ/RESP you need to manually handle the message envelope (the first frame of the message indicating its destination). Guide

    The 0MQ docs are incredibly dense... I don't blame you for not intuiting this from them :)

    This example from the NetMQ docs is full ROUTER-DEALER: https://netmq.readthedocs.io/en/latest/router-dealer/#router-dealer, you can take just the router side and it should work the same though.