【问题标题】:How to set up a ZeroMQ request-reply between a c# and python application如何在 c# 和 python 应用程序之间设置 ZeroMQ 请求-回复
【发布时间】:2021-03-24 05:46:47
【问题描述】:

我正在尝试通过 ZeroMQ 在 c#(5.0) 和 python (3.9) 应用程序之间进行通信。对于 .Net,我使用 NetMQ 和 python PyZMQ。

只要两个应用程序使用相同的语言,我就可以毫无问题地进行通信

  • c# 应用到 c# 应用;
  • 蟒蛇->蟒蛇;
  • java -> java,

但是当我尝试在不同语言之间进行连接时,麻烦就开始了。

  • java -> c# 和 reverse 也可以正常工作 [edited]

我没有收到任何错误,但它也不起作用。

我首先尝试了PUB-SUB Archetype 模式,但由于它不起作用,我尝试了REQ-REP,所以仍然可以找到 "PUB-SUB"-version 的一些剩余部分在代码中。

我的 Python 代码如下所示:

def run(monitor: bool):
loop_counter: int = 0

context = zmq.Context()
# socket = context.socket(zmq.PUB)
# socket.bind("tcp://*:5557")
socket = context.socket(zmq.REP)
socket.connect("tcp://localhost:5557")

if monitor:
    print("Connecting")

# 0 = Longest version, 1 = shorter version, 2 = shortest version
length_version: int = 0

print("Ready and waiting for incoming requests ...")

while True:
    message = socket.recv()

    if monitor:
        print("Received message:", message)

    if message == "long":
        length_version = 0
    elif message == "middle":
        length_version = 1
    else:
        length_version = 2

    sys_info = get_system_info(length_version)

    """if not length_version == 2:
        length_version = 2

    loop_counter += 1

    if loop_counter == 15:
        length_version = 1

    if loop_counter > 30:
        loop_counter = 0
        length_version = 0"""

    if monitor:
        print(sys_info)

    json_string = json.dumps(sys_info)
    print(json_string)
    socket.send_string(json_string)

我的 C# 代码:

static void Main(string[] args)
    {
        //using (var requestSocket = new RequestSocket(">tcp://localhost:5557"))
        using (var requestSocket = new RequestSocket("tcp://localhost:5557"))    
        {
            while (true) {
                Console.WriteLine($"Running the server ...");
                string msg = "short";
                requestSocket.SendFrame(msg);
                var message = requestSocket.ReceiveFrameString();
                Console.WriteLine($"requestSocket : Received '{message}'");
                //Console.ReadLine();
                Thread.Sleep(1_000);
            }
        }
    }

【问题讨论】:

  • 我在两个程序中都设置了断点(设置了相同的端口号:)),它确实似乎在发送数据(c#),但是 python 代码中的断点(就在 message = socket. recv()) 永远不会被激活。我尝试使用 requestSocket.SendFrameEmpty();在 C# 中,只是为了触发 Python 中的任何内容,但没有成功。
  • 如下所述,这只是一个附带项目,不幸的是我尝试解决这个问题的时间有限。我已经通过在 python 项目中转储 ZMQ(而不是在 Java 和 C# 中 - 一切正常)并用良好的旧 TCP 和套接字替换它来解决它,现在它工作得很好。我不知道如何处理这个问题,因为从技术上讲它还没有解决,但我当然不会再为此付出努力。我也不能发布我的 TCP 代码,因为这不是这个特定问题的答案。欢迎您的意见。

标签: zeromq publish-subscribe pyzmq netmq request-response


【解决方案1】:

看到你的问题的时期可能是因为版本。 我通过 Windows/C# 与 NTMQ 4.0.0.207 239,829 7/1/2019 和 Ubuntu/Python 与 zeromq=4.3.1 和 pyzmq=18.1.0 的通信长时间运行良好的程序。 我只是尝试更新以使用相同的 NETMQ 版本,但使用新版本 zeromq=4.3.3 和 pyzmq=20.0.0 但某处存在问题/错误,它不再运行良好。

所以你的代码看起来不错可能是它的软件版本问题在 c# 端尝试使用 NTMQ 4.0.0.207 和在 python 端使用 pyzmq=18.1.0 的 zeromq=4.3.1

【讨论】:

  • 感谢 totoleroi !正如我之前所说,我不再在通信中使用 zeromq,老实说我删除了那个项目,所以我不知道版本。但是,我会将您的答案标记为我的问题的答案,因为您有两个使用您提供的设置的工作程序,这比我有的要多。
【解决方案2】:

你的端口号不匹配,python代码是55557,c#是5557

【讨论】:

  • 我今天早上注意到了,把它都改成了5557,但还是一样。我现在在这里更新代码。感谢您提及。
【解决方案3】:

Q“如何在 c# 和 python 应用程序之间设置 ZeroMQ 请求-回复”

问题始于对 REQ/REP 原型如何工作的理解缺失。

您的代码使用了 .recv() 方法的阻塞形式,因此每当 REQ/REP 两步遇到麻烦时,您将永远处于游戏之外,永远无法挽救小心防止这种无限活锁)。

而是开始使用.poll()-方法开始测试队列的本地 AccessNode 端是否存在消息,这使您能够完全有状态地决定下一步做什么,如果有消息已存在或尚未存在,以便保持 API 定义的强制顺序需要“压缩”
REQ-side .send()-.recv() 的成功链接-.send()-.recv()-... 与
REP-side .recv()-.send()-.recv()-.send()-... 通话,是REQ/REP 原型作为分布式-Finite-State-Automaton (dFSA),由于“远程”端不符合本地方面的期望。

拥有一个在非阻塞、基于.poll() 的模式下工作的代码可以避免陷入这些陷阱,因为您可以在仍然控制代码执行路径(其中盲目地相信阻塞模式方法会在未来某个时间点返回,如果有的话,根本不可能)。

Q.E.D.


如果有疑问,可以使用 PUSH/PULL 原型,因为 PUB/SUB-archetype 可能会遇到订阅不匹配的问题(主题列表管理是另一个,版本相关的详细信息)。

任何语言绑定都应该没有其他问题,如果它们通过了所有记录在案的 ZeroMQ API 功能而不创建任何“快捷方式” - 在某些情况下,特定于语言的绑定对 @ 采取了“另一个”方向987654339@,在发送纯消息时,转换为多部分消息,将一个主题放入第一帧,将消息放入另一帧。这是与 ZeroMQ API 不兼容的绑定示例,其中跨语言/不匹配的绑定版本系统问题很明显。

【讨论】:

  • 感谢清晰易懂的解释!老实说,我的 python 代码基于 pyZMQ 的一个示例。这至少有点误导......我明天将修改我的代码,从现在开始我将在我使用 0MQ 的任何语言中使用异步方法!如果这解决了问题(正如我所料 - 因为它挂在 .recv 方法上),我将修改代码并在本主题中更新它。
  • 我刚刚修改了python代码进行轮询,但是没有结果。我来自 TCP 背景,我习惯于首先启动“服务器”,在这种情况下是 python 代码,这在你给出的解释中让我感到困扰。我应该至少从后来启动的 c# 请求者的初始启动中获得一个触发器,阻塞或非阻塞。由于这是一个副项目,我不能再花时间在它上面,并将尝试使用 tcp 或共享文件来解决它,无论是否可行。对我来说最重要的是,对于 Java 和 C# ZMQ 确实有效。无论如何,谢谢。
【解决方案4】:

我可能会迟到,但同样的事情也发生在我身上。我有一个使用 pyzmq 的 python 订阅者和一个使用 NetMQ 的 C# Publisher。

几个小时后,我突然想到我需要让发布者有一些时间来连接。所以在连接/绑定之后一个简单的System.Threading.Thread.Sleep(500); 就可以了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-15
    • 2016-03-22
    相关资源
    最近更新 更多