What is the proper way to wait for connections?
Asked Answered
N

3

7

I am trying to implement a simple message passing between two applications using NetMQ (a slightly more elaborate description of what I am trying to achieve is below).
After a bit of trial and error I've found that I can't just send or receive messages right away after a Connect/Bind calls, since they are non blocking and actually return even if the connection hasn't been established yet.
For now I solved this with Thread.Sleep(), but this has a bad taste to it and definitely a no-go for a production system.

So the question is, how's one supposed to do it in NetMQ/ZeroMQ?

Client example:

        using (NetMQContext ctx = NetMQContext.Create())
        {
            using (var client = ctx.CreatePushSocket())
            {
                client.Connect("tcp://127.0.0.1:5555");
                Thread.Sleep(100); // wait for connection

                for (int i = 0; i < 5; i++) 
                {
                    client.Send("test " + i , true);
                }
            }
        }
    }

Server example:

    using (NetMQContext ctx = NetMQContext.Create())
    {
        using (var server = ctx.CreatePullSocket())
        {
            server.Bind("tcp://127.0.0.1:5555");
            Thread.Sleep(100); // wait for connection
            while (true)
            {
                var str = server.ReceiveString();
                Console.Out.WriteLine(str);
                Thread.Sleep(60*1000); // do msg processing
            }
        }
    }

Description of what I am trying to achieve:

Client - Sends messages to a single server. The client should not block and should not discard messages when server is not available. The client can come offline/online at any time.

Server - Receives messages from a single client. The server blocks until a message is received. Server needs to do lengthy processing of the message and should not loose any other messages while processing. The server can come offline/online at any time.

Neve answered 28/3, 2014 at 14:37 Comment(1)
The example on the netmq site does not pass true in to Send.Schenk
S
7

The best solution to your sleep on the server side is to create a socket poller and poll on the pull socket until a message is received. This avoids wasteful sleeps, and makes for generally tighter code.

On the client side the best solution is probably to create two sockets (one for sending messages, one for receiving), and have the server announce its presence ready for the client to send the message. Because ZeroMQ is efficient at handling multiple connections, this solution will work very well.

Scevo answered 29/3, 2014 at 16:26 Comment(0)
T
10

both receive and send can wait until can be executed, you passed true to dontWait parameter on your example, just remove it and it will send the message when it can.

For the receive you don't have to sleep because it will wait until message is available.

As suggested using Poller is also a solution (you can poll when the socket can send and when messages are ready to be consumed), take a look at the testing for poller class: https://github.com/zeromq/netmq/blob/3.3.3-rc5/src/NetMQ.Tests/PollerTests.cs.

Triste answered 22/6, 2014 at 13:20 Comment(0)
S
7

The best solution to your sleep on the server side is to create a socket poller and poll on the pull socket until a message is received. This avoids wasteful sleeps, and makes for generally tighter code.

On the client side the best solution is probably to create two sockets (one for sending messages, one for receiving), and have the server announce its presence ready for the client to send the message. Because ZeroMQ is efficient at handling multiple connections, this solution will work very well.

Scevo answered 29/3, 2014 at 16:26 Comment(0)
L
0

For original question, blocking send/recv is a nice solution.

For really waiting a connection:

Before ØMQ/3.2, poll/select for write event is a satisfactory solution for bind side (server side). To have a write event, the socket MUST logically be able to send message in current state, thus this method is NOT applicable to SUB, PULL and REP socket. Connect side will create queue before connection established, thus the write event cannot indicate connected event.

After ØMQ/3.2 (include), we can use zmq_socket_monitor and monitor ZMQ_EVENT_CONNECTED.

Lir answered 16/8, 2023 at 15:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.