使用NetMQ 4.x无法使ReadyReceive pub-sub工作

时间:2017-06-23 16:51:27

标签: c# netmq

我创建了2个简单的C#控制台项目(.net 4.5.2),为每个程序添加了v4.0.0.1 NetMQ Nuget包,将每个程序加载到单独的Visual Studio 2017社区版中,在1行上添加断点包含在OnReceiveReady回调方法中,首先启动订阅者程序,然后启动发布者程序。订户中未触发ReceieveReady事件。我究竟做错了什么?即使我选择了subSocket.Subscribe(""),我仍然没有收到任何消息。此外,删除/修改发送/接收HighWatermarks也没有改变。谢谢你的帮助!

这是发布商代码:

using System;
using NetMQ;
using NetMQ.Sockets;
using System.Threading;

namespace SampleNQPub
{
    class Program
    {
        static void Main(string[] args)
        {
            var addr = "tcp://127.0.0.1:3004";

            using (var pubSocket = new PublisherSocket())
            {
                Console.WriteLine("Publisher socket binding.");
                pubSocket.Options.SendHighWatermark = 10;
                pubSocket.Bind(addr);

                for (int i=0; i < 30; i++)
                {
                    pubSocket.SendMoreFrame("NQ").SendFrame(i.ToString());
                    Thread.Sleep(1000);
                }

                pubSocket.Disconnect(addr);
            }
        }
    }
}

这是订阅者代码:

using System.Threading;
using NetMQ;
using NetMQ.Sockets;

namespace SampleNQSub
{
    class Program
    {
        static void Main(string[] args)
        {
            var addr = "tcp://127.0.0.1:3004";

            using (var subSocket = new SubscriberSocket())
            {
                subSocket.ReceiveReady += OnReceiveReady;
                subSocket.Options.ReceiveHighWatermark = 10;
                subSocket.Connect(addr);
                subSocket.Subscribe("NQ");

                for (int i=0; i < 20; i++)
                {
                    Thread.Sleep(1000);
                }

                subSocket.Disconnect(addr);
            }
        }

        static void OnReceiveReady(object sender, NetMQSocketEventArgs e)
        {
            var str = e.Socket.ReceiveFrameString();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

好的,这是NetMQ世界中的一个难题,我只是想出来了。你必须设置一个NetMQPoller,它将最终调用你添加到它的每个ReceiveReady回调(NetMQPoller)。

这是更正后的代码,至少(即,ReceiveFrameString仍然只获得&#34; NQ&#34;部分,但这只是另一个方法调用修复)得到触发的ReceiveReady事件:

using System.Threading;
using System.Threading.Tasks;
using NetMQ;
using NetMQ.Sockets;

namespace SampleNQSub
{
    class Program
    {
        static void Main(string[] args)
        {
            var addr = "tcp://127.0.0.1:3004";

            NetMQPoller poller = new NetMQPoller();

            using (var subSocket = new SubscriberSocket())
            {
                subSocket.ReceiveReady += OnReceiveReady;
                subSocket.Options.ReceiveHighWatermark = 10;
                subSocket.Connect(addr);
                subSocket.Subscribe("NQ");

                poller.Add(subSocket);
                poller.RunAsync();

                for (int i = 0; i < 20; i++)
                {
                    Thread.Sleep(1000);
                }

                subSocket.Disconnect(addr);
            }
        }

        static void OnReceiveReady(object sender, NetMQSocketEventArgs e)
        {
            var str = e.Socket.ReceiveFrameString();
            e.Socket.ReceiveMultipartStrings()
        }
    }
}

我注意到NetMQ的作者在4.x中决定在内部处理Context对象,因此用户不必承担管理它的负担。如果他们可以隐藏这个&#34;轮询泵&#34;那也很好。来自用户的代码以及最简单的用例。

作为比较,使用上面发布的Publisher控制台应用程序(使用zmq库)查看订阅者(将此代码保存到sub.js,并在Windows控制台中键入&#39;节点sub.js&#39):

var zmq = require('zmq'), sock = zmq.socket('sub');

sock.connect('tcp://127.0.0.1:3004');
sock.subscribe('NQ');
console.log('Subscriber connected to port 3004');

sock.on('message', function() {
    var msg = [];
    Array.prototype.slice.call(arguments).forEach(function(arg) {
        msg.push(arg.toString());
    });

    console.log(msg);
});

那么轮询泵机制在哪里呢? (答案:我不在乎!我只想在我注册的回调中提供给我的消息。[显然,诙谐。我认为NetMQPoller是多功能的,处理更复杂的问题,但对于基本&#34;当它到达时给我一个回调消息&#34;如果它是由库内部处理的话会很好。])