NetMQ в сети

Я пытаюсь сделать обмен сообщениями между программами на отдельных компьютерах в локальной сети. Дизайн в основном представляет собой один «сервер», несколько «клиентов», при этом сервер отправляет сообщения клиентам и получает сообщения от клиентов, а клиенты получают сообщения от сервера и отправляют/получают клиентские сообщения между собой.

Я пытаюсь использовать для этого NetMQ, но у меня возникают проблемы с его работой в сети. Я могу прекрасно запускать серверную и клиентскую программы на одной машине, но я не уверен, как заставить их работать в сети, и я не могу найти примеры NetMQ, которые показывают это — чтобы было ясно, < strong>каждый пример, который я могу найти, использует «localhost» или какой-либо другой IP-адрес для как «издателя», так и «подписчика» (я использую шаблон Pub-Sub, но я видели то же самое, независимо от шаблона, используемого в примере).

Некоторый пример кода, использующий инфраструктуру клиент-клиент (для этого требуется инфраструктура XPub-XSub, поскольку существует несколько издателей и подписчиков):

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();

Если я запускаю это, я получаю «приложение находится в режиме приостановки» со следующей ошибкой:

NetMQ.NetMQException HResult=0x80131500 Источник=NetMQ StackTrace: в NetMQ.Core.Transports.Tcp.TcpConnector.OutCompleted(SocketError socketError, Int32 bytesTransferred) в NetMQ.Core.IOObject.OutCompleted(SocketError socketError, Int32 bytesTransferred) в NetMQ.Core. Utils.Proactor.Loop() в System.Threading.ThreadHelper.ThreadStart_Context(состояние объекта) в System.Threading.ExecutionContext.RunInternal(ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта, логическое значение saveSyncCtx) в System.Threading.ExecutionContext.Run(ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта, логическое значение saveSyncCtx) в System.Threading.ExecutionContext.Run(ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта) в System.Threading.ThreadHelper.ThreadStart()

Если я изменю адрес clientSub на «tcp://127.0.0.1:5555», он запустится нормально. Однако это не сработает, поскольку подписчику необходимо получать сообщения с любого компьютера в сети.

Как мне это сделать с помощью NetMQ? Может ли кто-нибудь привести рабочий пример этого?


person Eternal Ambiguity    schedule 13.07.2019    source источник


Ответы (2)


По умолчанию при использовании конструктора сокета используется либо привязка, либо подключение, в зависимости от типа сокета. издатель привязывается (слушает), а подписчик подключается. Так что имеет смысл использовать * для подписчика.

Вы используете TCP-транспорт, поэтому при подключении вам необходимо указать IP-адрес удаленного узла. Если вы хотите подключиться к нескольким издателям, вы можете либо вызвать connect, либо предоставить строку s с несколькими адресами, разделенными запятыми.

В итоге вместо *, localhost или 127.0.0.1 используйте ip адрес машины издателя.

Вы можете использовать префиксы @ или > для переопределения значений конструктора по умолчанию. @ для привязки и > для подключения.

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 мой IP-адрес. Вам нужно изменить его на свой ip.

person somdoron    schedule 13.07.2019
comment
Идея подключения к нескольким конечным точкам от подписчика никогда не приходила мне в голову. Спасибо. Просто для ясности, это единственный способ сделать это с помощью clientSub.Connect() несколько раз? Я только что попробовал clientSub = new SubscriberSocket(›tcp//*:5555) и снова получил исключение NetMQException. - person Eternal Ambiguity; 15.07.2019
comment
«›» для подключения, вы не можете подключиться к «», «» используется как любой при привязке, при подключении вы должны использовать IP-адрес или DNS. - person somdoron; 15.07.2019

У меня есть простой пример. Мой «серверный» код работает на экземпляре Amazon EC2. Он прослушивает порт 11000 и отвечает на одно сообщение.

using System;
using NetMQ;
using NetMQ.Sockets;

class Program
{
    private static void Main()
    { 
        using (var server = new ResponseSocket("@tcp://*:11000"))
        {
            // the server receives, then sends
            Console.WriteLine("From Client: {0}", server.ReceiveFrameString());
            server.SendFrame("Hi Back");
            Console.ReadKey();
        }
    }
}

Мой клиентский код работает на моем ПК:

using System;
using NetMQ;
using NetMQ.Sockets;

class Program
{
    private static void Main()
    {
        using (var client = new RequestSocket(">tcp://3.13.186.250:11000"))
        {
            client.SendFrame("Hello");
            Console.WriteLine("From Server: {0}", client.ReceiveFrameString());
            Console.ReadKey();
        }
    }
}
person Cakemeister    schedule 20.12.2019