Search code examples
c#socketstcpzeromqnetmq

Communicating with a classic TCP socket


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?


Solution

  • 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:

    enter image description here