Search code examples
c#network-programmingnetmq

NetMQ On A Network


I'm trying to do messaging between programs on separate computers on a local network. The design is basically one "server," multiple "clients," with the server sending messages to the clients and receiving messages from the clients, and the clients receiving messages from the server, and sending/receiving client messages between each other.

I'm trying to use NetMQ for this, but I'm having trouble getting it working on a network. I can run the server and client programs perfectly fine on a single machine, but I'm not sure how to get it to work on a network, and I can't find any NetMQ examples that show this--to be clear, every example I can find uses "localhost" or some other IP address for both the "publisher" and "subscriber" (I'm using a Pub-Sub pattern, but I've seen the same regardless of the pattern used in the example).

Some example code using the client-client framework (this requires an XPub-XSub framework because there are multiple publishers and subscribers):

NetMQPoller poller = new NetMQPoller();
PublisherSocket clientPub = new PublisherSocket("tcp://*:4444");
XPublisherSocket xPub = new XPublisherSocket("tcp://*:5555");
XSubscriberSocket xSub = new XSubscriberSocket("tcp://*:4444");
Proxy proxy = new proxy(xSub, xPub, poller: poller);
proxy.Start();
SubscriberSocket clientSub = new SubscriberSocket("tcp://*:5555");
poller.Add(clientSub);
poller.Add(clientPub);
poller.RunAsync();

If I run this, I get "the application is in break mode" with the following error:

NetMQ.NetMQException HResult=0x80131500 Source=NetMQ StackTrace: at NetMQ.Core.Transports.Tcp.TcpConnector.OutCompleted(SocketError socketError, Int32 bytesTransferred) at NetMQ.Core.IOObject.OutCompleted(SocketError socketError, Int32 bytesTransferred) at NetMQ.Core.Utils.Proactor.Loop() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()

If I change the clientSub's address to "tcp://127.0.0.1:5555" it starts fine. However, that won't work because the subscriber needs to receive messages from any machine on the network.

How do I do this with NetMQ? Can anyone provide a working example of this?


Solution

  • By default when you use the constructor of a socket is either bind or connect, depends on the socket type. publisher bind (listen)and subscriber connects. So it does make sense to use * for the subscriber.

    You are using tcp transport, so you have to specify an ip address of the remote peer when connecting. If you want to connect to multiple publishers you can either call connect or provide s string with multiple addresses separated by comma.

    Bottom line instead of *, localhost or 127.0.0.1 use the ip address of the publisher machine.

    You can use the @ or > prefixes to override the defaults of the constructor. @ to bind and > to connect.

    NetMQPoller poller = new NetMQPoller();
    PublisherSocket clientPub = new PublisherSocket(">tcp://192.168.0.15:4444");
    XPublisherSocket xPub = new XPublisherSocket("@tcp://*:5555");
    XSubscriberSocket xSub = new XSubscriberSocket("@tcp://*:4444");
    Proxy proxy = new proxy(xSub, xPub, poller: poller);
    proxy.Start();
    SubscriberSocket clientSub = new SubscriberSocket(">tcp://192.168.0.15:5555");
    poller.Add(clientSub);
    poller.Add(clientPub);
    poller.RunAsync();
    

    192.168.0.15 is my ip address. You need to change it to your ip.