Can ZeroMQ be used to accept traditional socket requests?
Asked Answered
V

2

8

I'm trying to re-write one of our old Servers using ZeroMQ, for now I have the following Server setup, (which works for Zmq requests):

    using (var context = ZmqContext.Create())
    using (var server = context.CreateSocket(SocketType.REP)) {
        server.Bind("tcp://x.x.x.x:5705");

        while (true) { ... }

This kind of setup works fine if I use the Zmq client library to connect context.CreateSocket(SocketType.REQ)

But unfortunately we've got a lot of legacy code that needs to connect to this server and the sockets are created using .net socket libs:

    Socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
    Socket.Connect(ipAddress, port);

Is there a way to write a ZeroMQ Server to accept these traditional .net socket connections?

Vanvanadate answered 18/6, 2013 at 19:4 Comment(0)
P
16

You can achieve this using ZMQ_STREAM sockets.

Please note that since zeroMQ 4.x, the RAW router option has been deprecated for a new ZMQ_STREAM socket type, that works the same way as ROUTER + RAW.

It seems it is bound to evolve, though.

I recently tried ZMQ_STREAM sockets in version 4.0.1.

You can open one, use zmq_rcv until you receive the whole message (you have to check it is whole yourself), or zmq_msg_rcv to let ZeroMQ handle it. You will receive an identifier message part, just like the identifier you would find in ROUTER sockets, directly followed by one ONLY body part. There is no empty delimiter between them like there would be using a REQ Socket talking to a ROUTER Socket. So if you route them, be sure to add it yourself.

Beware though: if there is latency on the other end or if your message exceeds ZeroMQ ZMQ_STREAM buffers (mine are 8192 bytes long), your message can be interpreted by zeroMQ as a series of messages.

In that case, you will receive as many different ZeroMQ messages including both the identifier part and the body part, and it is your job to aggregate them, knowing that if several clients are talking to the STREAM socket, they might get mixed up. I personnally use a hash table using the binary identifier as a key, and delete the entry from the table when I know the message is complete and sent to the next node.

Sending through a ZMQ_STREAM with zmq_msg_send or zmq_send works fine as is.

Pleurisy answered 4/12, 2013 at 16:34 Comment(0)
D
4

You probably have to use zmq's RAW socket type (instead of REP) to connect with and read client data without zmq-specific framing.

HTTP Server in C (from Pieter's blog)
http://hintjens.com/blog:42

RAW Socket type info
https://github.com/hintjens/libzmq/commit/777c38ae32a5d1799b3275d38ff8d587c885dd55

Dionisio answered 18/6, 2013 at 20:34 Comment(3)
Hey @Raffian, thanks, but not sure how to implement this. There is no SocketType of RAW, do you have an example you could provide?Vanvanadate
Yes, here's one Pieter wrote, hintjens.com/blog:42, it's basically a HTTP server using zmq raw sockets, it's in C, but you should be able to port it to .net, as long as .net it supports RAW socket, I know the pure Java zmq library (jeromq) does not...hope it helps.Dionisio
Thank @Raffian, I can't link directly to the ZMQ lib, I'm using clrzmq, the .Net implementation so this may not be possible thenVanvanadate

© 2022 - 2024 — McMap. All rights reserved.