3

I am currently using ZMQ as my means of sending information between a C# server and multiple C++ clients. ZMQ has worked perfectly up to this point due to the standard protocol between the different languages.

But now as my protocol has evolved, I am running into a wall with ZMQ. My protocol requires me to know which endpoint I am currently speaking to so I can apply the correct RSA key to the sent message.

It might help to give a brief overview of what I need done. I am using REQ and REP sockets. Clients use the REQ sockets and the server uses a REP socket.

  1. Each client connects via socket.connect() to the server over tcp and sends a quick request to let the server know it is there.
  2. The server receives the request by polling the socket every second and raising a receiveReady event.The server notifies the client to generate the private/public keys by sending the command via a string.
  3. The client does so and then sends the public key up to the server again via a string.
  4. Once the server obtains the key, it creates a Client object that stores the key and the socket to that client. (This is where the protocol breaks).
  5. Then whenever the server needs to send information out to the clients, it loops through the Client objects and encrypts and sends the message to the correct recipient.

I had assumed that the Socket in SocketEventArgs returned a socket to the endpoint that raised the event. (Similar to accepting a connection in non-ZMQ C#) This appears to be wrong. The socket in SocketEventArgs appears to be the "global" socket that all clients connect to. So I end up losing track of my sockets as clients connect.

So my question is, how do I make this work? I would love to keep ZMQ if possible, as it has been very nice to work with and solves lots of small edge cases for me. If that is not possible, is there another similar framework to ZMQ that would allow me to reference specific endpoints?

By the way I am using the current stable release of ZMQ which is 3.2.3, along with clrzmq for C#.

EDIT: Thinking on it, one solution might be to prepend each message with a string to identify the socket. As the current implementation only encrypts the information going downstream to the clients. Though this worries me as someone with a packet sniffer might be able to impersonate another client fairly easily.

EDIT2: This stackoverflow question is similar to mine Identifying the origin of ZMQ messages? and supports the notion that I will have to somehow identify every message I send to the server. But for my specific case, I don't care about the IP address or anything like that. I just want to be able to store endpoints so I can talk to them later. It's starting to seem like this is not going to be possible with ZMQ.

Does this sound reasonable?

  1. Each client connects to the server and sends a quick request to let the server know it is there. The request contains a unique id prepended in the first frame.
  2. The server than acknowledges the request and notifies the client to generate the private/public keys.
  3. The client does so and then sends the public key up to the server.
  4. Once the server obtains the key, it creates a Client object that stores the key and the unique id of the client.
  5. Then the clients poll the server for new information every few seconds.
  6. Whenever the server has new information to send it waits for the client to poll the server and then replies on the socket to that client. (This is now what worries me. How do I ensure that when the "global" socket, that every client connects to, recieves a message that the next message I send goes to that same endpoint?)

EDIT3: I can't believe I forgot to put in my socket types. I am currently using the REQ-REP pattern where each client is of the socket type REQ and the server is the REP socket. The server is bound to a port and the clients connect directly to it. All of this is done over tcp as the clients can be anywhere in the world.

EDIT4: I have updated the original implementation with some more specifics.

Community
  • 1
  • 1
Andy Eskridge
  • 260
  • 2
  • 14
  • 1
    You've written a lot, but the important details are missing... What socket types are you using? What is the exact network topology (who binds, who connects to who)? – Timothy Shields May 06 '13 at 18:40
  • @TimothyShields Thanks for pointing that out. I've updated the original post with the socket types and other info. I'm not doing anything crazy with my implementation, but I'll try to edit my post with a better overview of what is currently happening in my program. – Andy Eskridge May 06 '13 at 19:19
  • I've might have hit the holy grail with ZeroMQ.Monitoring that is found in the clrzmq.dll. It looks to be based off of http://api.zeromq.org/3-3:zmq-ctx-set-monitor. I am going to test this and see if solves some of my problems. – Andy Eskridge May 06 '13 at 19:50
  • 1
    If you use a ROUTER socket for your server rather than a REP socket and a DEALER socket for each client rather than a REQ socket, you can get much more fine grain control over the client-server messaging patterns. – Timothy Shields May 06 '13 at 20:16
  • 1
    Thank you very much @TimothyShields. It looks like the Router-Dealer implements the identity in exactly the way I was looking to do it. I will switch over to this pattern and see if it solves my problems. – Andy Eskridge May 06 '13 at 20:32
  • 1
    DEALER doesn't require a [Send, Recv, Send, Recv, ...] pattern. ROUTER doesn't require a [Recv, Send, Recv, Send, ...] pattern. When a client sends [X] to a ROUTER, the router receives [I, X] where I is the identity of the sender. When a ROUTER sends a message [I, X], the connected socket with identity I receives message [X]. – Timothy Shields May 06 '13 at 21:23
  • @TimothyShields How to can I in the `ZMQ_ROUTER` side, when I receive a message from one peer `ZMQ_DEALER`, send this message to another `ZMQ_DEALER` peer? I will need that the router know both identities of `ZMQ_DEALER` peers previously, store them and send the message using these identities ? I have this question just in case https://stackoverflow.com/questions/49289072/zmq-dealer-router-communication – bgarcial Mar 16 '18 at 16:46

1 Answers1

2

Use the ROUTER-DEALER pattern as described in the comments on the question.

Timothy Shields
  • 75,459
  • 18
  • 120
  • 173