【问题标题】:ZeroMQ PUB / C# SUB not working when subscriber started before publisher当订阅者在发布者之前启动时,ZeroMQ PUB / C# SUB 不起作用
【发布时间】:2017-11-05 17:26:56
【问题描述】:

在运行 ZeroMQ 基本 PUB / SUB C# 示例时,如果我先启动发布者,它们对我有用,但如果我先启动订阅者,则不会。当我这样做时,订阅者启动,但从未收到任何数据。根据我的阅读,我认为我应该能够以任一顺序启动进程。

我在 .NET 4.6、x64 应用程序中使用来自 nuget 的 ZeroMQ 4.1.0.26 包。这些在 Windows 上运行。我在同一台机器上运行这两个应用程序。

这是我正在运行的代码(它是 ZeroMQ 教程中示例的简化版本)。

订阅者:

    static void Main(string[] args)
    {
        var endpoint = "tcp://127.0.0.1:5556";

        // Socket to talk to server
        using (var context = new ZContext())
        using (var subscriber = new ZSocket(context, ZSocketType.SUB))
        {
            Console.WriteLine("I: Connecting to {0}…", endpoint);
            subscriber.Connect(endpoint);

            // Subscribe to zipcode
            string zipCode = "90210 ";
            Console.WriteLine("I: Subscribing to zip code {0}…", zipCode);
            subscriber.Subscribe(zipCode);

            while(true)
            {
                using (var replyFrame = subscriber.ReceiveFrame())
                {
                    string reply = replyFrame.ReadString();
                    Console.WriteLine(reply);
                }
            }
        }
    }

出版商:

    static void Main(string[] args)
    {
        using (var context = new ZContext())
        using (var publisher = new ZSocket(context, ZSocketType.PUB))
        {
            var address = "tcp://*:5556";
            Console.WriteLine("I: Publisher.Bind'ing on {0}", address);
            publisher.Bind(address);

            // Initialize random number generator
            var rnd = new Random();
            while (true)
            {
                // Get values that will fool the boss
                int zipcode = 90210;
                int temperature = rnd.Next(-55, +45);

                // Send message to all subscribers
                var update = string.Format("{0:D5} {1}", zipcode, temperature);
                using (var updateFrame = new ZFrame(update))
                {
                    publisher.Send(updateFrame);
                }

                Thread.Sleep(1000);
            }
        }
    }

编辑

我尝试了以下建议答案中的建议:

  • 使用明确的 IP 地址:这没有区别
  • 删除主题过滤:这没有区别
  • 创建新的 AnyCPU(而不是 x64)项目:这没有不同
  • 尝试其他语言:这很有趣!

使用 Python 等效的发布者和订阅者:

  • 在连接到 Python 发布者或 C# 发布者时,Python 订阅者在发布者之前启动时工作。
  • C# 订阅者在发布者之前启动时不起作用,无论它是连接到 Python 还是 C# 发布者。

所以看起来 C# 订阅者代码有问题。

问题:

  • 我的示例代码(以下最新版本)有问题吗?

  • 还是 ZeroMQ .NET 库有问题?

这是正常工作的 Python 订阅者:

import sys
import zmq

#  Socket to talk to server
context = zmq.Context()
socket  = context.socket( zmq.SUB )

print( "Python: Collecting updates from weather server" )
socket.connect( "tcp://localhost:5556" )

socket.setsockopt_string( zmq.SUBSCRIBE, "" )

while True:
    string = socket.recv_string()
    zipcode, temperature = string.split()
    print( zipcode + " " + temperature )

这是 C# 订阅者的最新等效 ( non-working ) 版本:

static void Main(string[] args)
{
    // Socket to talk to server
    using (var context = new ZContext())
    using (var socket = new ZSocket(context, ZSocketType.SUB))
    {
        Console.WriteLine("C#: Collecting updates from weather server");
        socket.Connect("tcp://localhost:5556");
        socket.Subscribe("");

        while (true)
        {
            using (var replyFrame = socket.ReceiveFrame())
            {
                string reply = replyFrame.ReadString();
                Console.WriteLine(reply);
            }
        }
    }
}

【问题讨论】:

  • netmq(zeromq 到 .net 的另一个端口)顺便说一句正确地做到了这一点。我会在这里打开一个问题:github.com/zeromq/clrzmq4 看看他们会说什么,你的代码看起来对我完全有效。
  • 订阅空字符串是否有效?
  • @somdoron 嗨,somdoron,“订阅任何东西”模式已经过 OP 测试,报告说它在 C# 中不起作用,而 python 客户端运行良好(参考根目录上的 cmets-下面的原因隔离测试 + 希望理查德很清楚,删除主题过滤器实际上意味着需要显式订阅一个空的 ""-string )。到目前为止,该问题似乎已被区分为 Richard 正在使用的 ZeroMQ C# 绑定的实际版本,如 SUB 端对比 { !working |在 C# 之间工作,分别。 python SUB 实现。
  • 好吧,ZeroMQ/clrzmq4 只是围绕 ZeroMQ/libzmq 的绑定;您应该尝试将 amd64/libzmq.dll/.so 替换为您的库版本。我怀疑你正在运行 Windows,其中最新的更新是对 libzmq 4.2.x 进行的,这实际上是一个测试版。请务必制作 ZeroMQ/zeromq4-1(或从您的 Python 绑定中复制一个),然后重试...

标签: c# zeromq


【解决方案1】:

如果您愿意一步一步地跟随the flow-chart re-published herePUB/SUB 的问题就会突出显示。

最近 (EoY-2017) API v4.x 重新设计工作改变了一些设计方法(主题过滤器是否在 SUB 端进行处理,因为它是 v2 .1+,或者——在较新的 API 版本中——在 PUB 一侧,反转开销分布/集中,exgress-flow buffering+traffic/processing-overhead ),然而,PUB/SUB 的操作顺序似乎保持不变(参考上面提到的流程图)。


事后根本原因隔离测试:

Python SUB 工作正常,我的 C# 不能。不清楚为什么:

感谢积极的代码重新测试,这有助于在根本原因歧视方面向前迈进了几步。

现在让我们关注为什么:

ZeroMQ 通常有两个抽象层,ZeroMQ 内部 一个,实现框架的核心功能,如 ZeroMQ 协议 RFC 规范中所定义。这是负责所有 RFC 定义的交互变得兼容和交叉兼容的部分,以便以 ZeroMQ 发布的方式服务。

另一层由“外来语”-语言包装器/API 绑定构成,帮助其他非本地语言(非 ZeroMQ 内部代码)使用ZeroMQ API 为任何特定的第 3 方语言中介公开的服务,以便“外部”世界有机会在内部 ZeroMQ 层的世界中调用由库实现的服务。

因此,差异被隔离使用 python SUB-probe(按定义运行良好)与 C# 语言绑定SUB-probe 仍然无法工作。

正如 Dijkstra 在测试中指出的那样,一些测试按预期工作并不意味着系统中没有其他错误/错误,绑定可能存在更多问题,但是来自 python @987654329 的积极确认@-client 表明,ZeroMQ 核心服务并不是导致错误的罪魁祸首。


A1:不,

您的代码似乎没问题。

A2:是的,

如上所述,这是主要的可疑 ATM

向 C# 绑定维护者报告修复 ZeroMQ 不合规行为的请求,如上面观察和重新测试的那样详细记录,是最好的下一步,以帮助不合规的人C# 绑定可以轻松工作。

【讨论】:

  • (不是 OP)。我遵循图表并以“查看文本中慢速加入者的解释”结束。在您的答案文本中没有找到,但我知道那是什么。但在这种情况下,PUB 不会错过发布者在连接之前可能发送的 一些 消息,它会错过 所有 条消息(发布者每秒发送 1 条消息),包括发布者之后发送的消息边界。这是为什么呢?
  • OP here:我同意 Evk 的上述评论,即我没有收到任何消息。所以我不认为这只是一个缓慢加入的问题(我很乐意接受并以其他方式处理)。
  • 第 0 步: 从 Pieter HINTJENS 的“Code Connected, Volume 1”一书中获取所有慢连接者详细信息的最佳开始,pdf 在这里 >>> hintjens.wdfiles.com/local--files/main%3Afiles/cc1pe.pdf 第 1 步: 设置 .bind()/.connect() 以对显式 IP 地址进行操作,而不依赖于通配符转换。接下来为了隔离根本原因,消除一个主题过滤器——订阅 SUB 端的所有消息。 第 2 步: 为了隔离 C# 绑定,接下来测试 .connect() 也来自另一个节点(无论是 python 还是其他选择的语言),以证明正确的消息传递。
  • 感谢 cmets user3666197 - 我已经完成了您建议的实验并编辑了我的问题。总结是:我的 Python 订阅者工作正常,我的 C# 订阅者没有。不过,我不清楚为什么!
  • 一旦另一种语言绑定的代码(这里是 python)工作,我怀疑原始语言绑定不满足提供真正中立的 ZeroMQ API 中介的要求。 如果使用非阻塞.poll() 确实查看{ "2" | "" } 订阅的客户端是否确实进入了传递方案并将任何消息放入它的传入队列缓冲区,会发生什么? 同样可能在另一个 port# 上测试并行 PAIR/PAIR 套接字原型的设置,从而验证 .ReceiveFrame() 方法的依赖链的另一部分。
猜你喜欢
  • 1970-01-01
  • 2020-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多