0

I have a problem with ZeroMQ on C# to send a message to a specific worker.

The architecture of the application is as follows:

Architecture of the application

I want to send a message from "client1" to "worker2" for example. But my application send to "worker1" then "worker2" for the next step.

Code for my Workers which are connected to the Dealer:

public static void RRWorker(string[] args)
{
    if (args == null || args.Length < 2)
    {

        if (args != null)
        {
            if (args.Length < 1)
            {
                args = new string[] { "World", "tcp://127.0.0.1:5560" };
            }
            else
            {
                args = new string[] { args[0], "tcp://127.0.0.1:5560" };
            }
        }
        else
        {
            args = new string[] { "World", "tcp://127.0.0.1:5560" };
        }
        
    }

    string name = args[0];

    string endpoint = args[1];

    // Socket to talk to clients
    using (var context = new ZContext())
    using (var responder = new ZSocket(context, ZSocketType.REP))
    {
        responder.IdentityString = name;
        responder.Connect(endpoint);
        Console.WriteLine("Ready : " + name);

        while (true)
        {
            // Wait for next request from client
            using (ZMessage request = responder.ReceiveMessage())
            {                       
                Console.WriteLine("W "+name +" .Message count : " + request.Count);
                for (int i =0; i< request.Count; i++)
                {
                    Console.WriteLine("--W--" + request[i]);
                }
                // Send reply back to client
                Console.WriteLine("Worker Name : {0}... ", name);
                responder.Send(new ZFrame(name));
            }
        }
    }
}

My code for the clients:

 public static void RRClient(string name)
{
    // Socket to talk to router
    using (var context = new ZContext())
    using (var requester = new ZSocket(context, ZSocketType.REQ))
    {
        requester.IdentityString = name;
        //requester.Identity = Encoding.Unicode.GetBytes(name);
        requester.Connect("tcp://127.0.0.1:5559");
        ZFrame messageContent;
        ZFrame destination;

        var outgoing = new ZMessage();
        destination = new ZFrame("Worker2");
        messageContent = new ZFrame("test Message");
        
        outgoing.Append(destination);
        outgoing.Append(new ZFrame());
        outgoing.Append(messageContent);

        requester.Send(outgoing);
        using (ZFrame reply = requester.ReceiveFrame())
            {
                Console.WriteLine("Client request : Hello {0}!", reply.ReadString());
            }
    }
}

My code for my Broker (router/dealer) :

public static void RRBroker(string[] args)
{
    // Prepare our context and sockets
    using (var ctx = new ZContext())
    using (var frontend = new ZSocket(ctx, ZSocketType.ROUTER))
    using (var backend = new ZSocket(ctx, ZSocketType.DEALER))
    {
        frontend.Bind("tcp://*:5559");
        backend.Bind("tcp://*:5560");

        // Initialize poll set
        var poll = ZPollItem.CreateReceiver();

        // Switch messages between sockets
        ZError error;
        ZMessage message;
        ZMessage messageTosend;
        while (true)
        {
            if (frontend.PollIn(poll, out message, out error, TimeSpan.FromMilliseconds(64)))
            {                       
                for (int i = 0; i < message.Count; i++)
                {
                    Console.WriteLine("--F--" + message[i].ReadString());
                }
                Console.WriteLine("-----" + GloFunction.ZMessageToString(message) + "---");
                backend.Send(message);
            }
            else
            {
                if (error == ZError.ETERM)
                    return; // Interrupted
                if (error != ZError.EAGAIN)
                    throw new ZException(error);
            }

            if (backend.PollIn(poll, out message, out error, TimeSpan.FromMilliseconds(64)))
            {
                Console.WriteLine("B Message count : " + message.Count);
                for (int i = 0; i < message.Count; i++)
                {
                    Console.WriteLine("--B--" + message[i].ToString());
                }                       
                GloFunction.Console_WriteZMessage("backend", 2, message);
                
                frontend.Send(message);
            }
            else
            {
                if (error == ZError.ETERM)
                    return; // Interrupted
                if (error != ZError.EAGAIN)
                    throw new ZException(error);
            }
        }
    }
}

To run my application, I create all my devices (router, dealer, client1, client2, worker1, worker2) in specifics threads.

Example when I run my "client1" twice :

Ready : Worker2
Ready : Worker1

--F--Client1
--F--
--F--Worker2
--F--
--F--test Message
-----Client1Worker2test Message---
W Worker2 .Message count : 3
--W--Worker2
--W--
--W--test Message
Worker Name : Worker2... 
B Message count : 3
--B--Client1
--B--
--B--Worker2
backend: Worker2
Client request : Hello Worker2!
Le thread 0x3d74 s'est arrêté avec le code 0 (0x0).

--F--Client1
--F--
--F--Worker2
--F--
--F--test Message
-----Client1Worker2test Message---
W Worker1 .Message count : 3
--W--Worker2
--W--
--W--test Message
Worker Name : Worker1... 
B Message count : 3
--B--Client1
--B--
--B--Worker1
backend: Worker1
Client request : Hello Worker1!
Le thread 0x4fd4 s'est arrêté avec le code 0 (0x0).

What am I doing wrong?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
QuentinMrt
  • 13
  • 3

1 Answers1

0

The Dealer-Router as proxy topology allows you to connect clients and services without knowing about the other, and allows you to dynamically add more clients/services which only need to know about the Dealer/Router. You can read more here: https://zguide.zeromq.org/docs/chapter2/#sockets-and-patterns (Figure 16 - Extended Request-Reply)

If I understand correctly - you do want a coupling between one client (REQ) and on service (REP) - for this you'll need to connect them directly

Yom B
  • 228
  • 1
  • 10