当订阅服务器在发布服务器之前启动时,ZeroMQ发布/C#SUB不工作

当订阅服务器在发布服务器之前启动时,ZeroMQ发布/C#SUB不工作,c#,zeromq,C#,Zeromq,在运行ZeroMQ basic PUB/SUB C#samples时,如果我先启动发布服务器,则它们对我有效,但如果我先启动订阅服务器,则不起作用。当我这样做时,订阅服务器启动,但从未收到任何数据。根据我所读到的,我认为我应该能够以任意顺序启动流程 我在.NET4.6x64应用程序中使用nuget的ZeroMQ 4.1.0.26包。这些都在Windows上运行。我在同一台机器上运行这两个应用程序 以下是我正在运行的代码(这是ZeroMQ教程中示例的简化版本) 订户: static voi

在运行ZeroMQ basic PUB/SUB C#samples时,如果我先启动发布服务器,则它们对我有效,但如果我先启动订阅服务器,则不起作用。当我这样做时,订阅服务器启动,但从未收到任何数据。根据我所读到的,我认为我应该能够以任意顺序启动流程

我在.NET4.6x64应用程序中使用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)
{
    // 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);
            }
        }
    }
}
出版商:

    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#subscriber的最新等效(非工作版)版本:

    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)
{
    // 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);
            }
        }
    }
}

如果您愿意一步一步地遵循,那么发布/订阅的问题就会突出显示出来

最近(EoY-2017)API v4.x重新设计工作改变了一些设计方法(无论主题过滤器是在
端进行处理(自v2.1+以来),还是在较新的API版本中,在
端进行处理,颠倒开销分布/集中、exgress流缓冲+流量/处理开销)然而,
PUB/SUB
的操作顺序似乎保持不变(参考上述流程图)


事后根本原因隔离测试:

Python SUB工作正常,而我的C#one不正常。不清楚原因: 感谢主动代码重新测试,这有助于在根本原因识别方面向前推进几步

现在让我们关注一下原因:

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

另一层由“外语”包装器/API绑定构成,它帮助ZeroMQ内部代码非本地的其他语言将ZeroMQ API公开的服务用于任何特定的第三方语言中介,如“外语”-世界有机会在内部ZeroMQ层的世界中调用由库实现的服务

因此,使用python
-probe将差异隔离到C#language binding,其中
SUB
-probe仍然不工作

正如Dijkstra在测试中指出的那样,一些测试按预期工作的事实并不意味着系统中没有其他bug/错误,绑定可能会有更多的问题,但是python
SUB
-客户端的肯定确认表明,ZeroMQ核心服务不是导致er的罪魁祸首罗


A1:没有, 你的代码看起来不错

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


向C#binding维护人员报告修复ZeroMQ不合规行为的请求(如上所述详细记录并重新测试),这是帮助不合规C#binding摆脱工作麻烦的最佳下一步。

(而不是OP)。我按照图表进行操作,并以“请参阅文本中的慢速Joiner解释”结束。在您的回答文本中未找到,但我知道这是怎么回事。但在这种情况下,PUB不会错过publisher在连接之前可能发送的某些邮件,而是会错过所有邮件(publisher每秒发送一条邮件),包括出版商绑定后发送的。为什么?请点击此处:我同意上面Evk的评论,即我没有收到任何消息。因此,我不认为这只是一个缓慢加入的问题(我很乐意接受并以其他方式处理)。第0步:最好从Pieter HINTJENS的书中获取所有缓慢加入的详细信息“Code Connected,Volume 1”以pdf格式在此处提供>>>步骤1:将.bind()/.connect()设置为在显式IP地址上操作,而不依赖通配符转换。下一步为了隔离根本原因,消除主题筛选器--订阅子端的所有消息。步骤2:要隔离C#绑定,请下一步测试.connect()也可以从另一个节点(无论是python还是其他选择的语言)为了证明正确的消息传递。感谢用户3666197的评论-我已经做了您建议的实验并编辑了我的问题。总结是:我的Python订阅者工作正常,我的C#one没有。但我不清楚为什么!另一种语言绑定的代码(这里是Python)作品中,我怀疑原版语言装订不符合要求