How to dispose of Sockets, Monitors and Pollers in NetMQ / ZeroMQ correctly?

106 views Asked by At

I'm working with C#, Unity and NetMQ (ZeroMQ for c#). I'm creating and connecting/binding a PublisherSocket and SubscriberSocket and are monitoring it with a NetMQPoller and NetMQMonitor. I'm doing the following:

m_Publisher = new PublisherSocket();
m_Subscriber = new SubscriberSocket();
m_Poller = new NetMQPoller();
m_SubMonitor = new NetMQMonitor(m_Subscriber, m_InprocSubMonitorAddress, SocketEvents.Connected | SocketEvents.Disconnected);

// Events
m_SubMonitor.Connected += (s, e) =>
{
    Connected = true;
    UnityMainThreadDispatcher.Instance().Enqueue(() => OnConnected?.Invoke(this, EventArgs.Empty));
};

m_SubMonitor.Disconnected += (s, e) =>
{
    Connected = false;
    UnityMainThreadDispatcher.Instance().Enqueue(() => OnDisconnected?.Invoke(this, EventArgs.Empty));
};

// Monitoring
m_SubMonitor.AttachToPoller(m_Poller);
m_Poller.RunAsync();

// Subscriber
m_Subscriber.Connect($"tcp://{m_IPAddress}:{m_Port}");

// Publisher
m_Publisher.Bind($"tcp://*:{m_Port}");

Feel free to correct me, if that is the wrong way to do it, but its working. The problem occurs when trying to connect to an address, which is not online (so Connected Event is never invoked). It should be possible to cancle the Connection attempt and try to connect again afterwards. On the second attemp I get an "Address already in use" Error, stating the m_InprocSubMonitorAddress ("inproc://sub.inproc") and pointing to the creation of the NetMQMonitor. My guess is, that I'm not disposing of the Sockets, Poller and Monitor correctly, but I cant seem to get it right. I've tried multiple ways, the current beeing:

m_SubMonitor.DetachFromPoller();
m_Poller?.Stop();
m_Poller?.Dispose();
m_SubMonitor?.Stop();
m_SubMonitor?.Dispose();

m_Publisher?.Unbind($"tcp://*:{m_Port}");
//m_Publisher?.Close();
m_Publisher?.Dispose();

m_Subscriber?.Disconnect($"tcp://{m_IPAddress}:{m_Port}");
//m_Subscriber?.Close();
m_Subscriber?.Dispose();

What would be the correct way? It is not possible for me to use using, because I'm working with the sockets in multiple functions and threads. Do I need to call NetMQConfig.Cleanup on each disconnect? Currently I'm calling it once, when the Application Quits. I'm also passing false into it, so it should not block. Is that correct?

I appreciate any help!

1

There are 1 answers

0
Aleksandr Zolotov On

It's a really depends from your situation.

For example you can use CleanUp concept , but in my case it have side effects. When I use cleanup inside my application I can count all connections and never make more 1. But when I create API, then applications are using it without care about. So when my API library cleaning up socket Net MQ inside destroy not only currect socket connection but all others too ...