I'm writing my first application with NetMQ (ZeroMQ implementation for .NET).
I also need to listen to information sent from a client using a traditional TCP socket (a.k.a a non-0MQ socket).
I've seen references to the availability of this socket type in the official ZeroMQ documentation here, (look for ZMQ_STREAM), but there's very few details on how to use it (and that doesn't help much either, the .NET API is quite a bit different from the C++ API).
The offical NetMQ documentation also makes no mention of the Streaming socket type.
Finally I had a look over to the Test suite for NetMQ on Github, and found a partial answer to my question in the method RawSocket.
The following snippet works:
using (NetMQContext context = NetMQContext.Create())
{
using (var routerSocket = context.CreateRouterSocket())
{
routerSocket.Options.RouterRawSocket = true;
routerSocket.Bind("tcp://127.0.0.1:5599");
byte[] id = routerSocket.Receive();
byte[] message = routerSocket.Receive();
Console.WriteLine(Encoding.ASCII.GetString(id));
Console.WriteLine(Encoding.ASCII.GetString(message));
}
}
When using standard TCP/IP test-tools, the byte[] message is printed out nicely, e.g. like this:
Hello World!
but the byte[] id is printed out like this:
???♥
In other words, I have no clue what's up with the id part. Why is routerSocket.Receive called twice? What is contained within the id? Is this something ZeroMQ/NetMQ specific, or is something TCP/IP specific information being extracted here?
Thanks to @Mangist for pointing this out.
The answer is in the RouterSocket documentation:
An identity, sometimes called an address, is just a binary string with no meaning except "this is a unique handle to the connection". Then, when you send a message via a ROUTER socket, you first send an identity frame.
When receiving messages a ZMQ_ROUTER socket shall prepend a message part containing the identity of the originating peer to the message before passing it to the application. Messages received are fair-queued from among all connected peers. When sending messages a ZMQ_ROUTER socket shall remove the first part of the message and use it to determine the identity of the peer the message shall be routed to.
Identities are a difficult concept to understand, but it's essential if you want to become a ZeroMQ expert. The ROUTER socket invents a random identity for each connection with which it works. If there are three REQ sockets connected to a ROUTER socket, it will invent three random identities, one for each REQ socket.
This image illustrates the core concept of the ID frames: