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

How to set up a ZeroMQ request-reply between a c# and python application

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

我可以让两个应用程序通信,只要它们使用相同的语言

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

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

我首先尝试了 PUB-SUB 原型模式,但由于它不起作用,我尝试了 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);
            }
        }
    }

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

Q : "How to set up a ZeroMQ request-reply between a c# and python application"

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

您的代码使用了 .recv() 方法的阻塞形式,因此无论何时 REQ/REP 两步执行,您都将自己挂在游戏之外,永远且无法挽救陷入麻烦(因为没有采取适当的措施来防止这种无限的活锁)。

而是开始使用 .poll() 方法开始测试队列的本地 AccessNode 端是否存在消息,这使您能够状态完全决定下一步做什么, 如果消息已经存在或尚未存在,为了保持 API 定义的强制序列,需要“压缩”
[=14= 的成功链接]-边.send()-.recv()-.send()-.recv()-...与
REP-side .recv()-.send()-.recv()-.send()-...调用,REQ/REP原型是否作为distributed-Finite-State-Automaton (dFSA),由于“远程”端与本地端不兼容,因此很容易发生死锁期望。

拥有一个在非阻塞、基于 .poll() 的模式下工作的代码可以避免落入这些陷阱,因为您可以在处理这些不需要的情况的同时仍然控制代码-执行路径(盲目相信它会 return 在未来的某个时间点调用阻塞模式方法,如果有的话,根本无法实现)。

Q.E.D.


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

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

看你问题的周期,可能是版本的问题。 我 运行 长时间通过 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 但是某处有一个 problem/bug,它不再 运行 好。

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

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

几个小时后,我想到我需要让 Publisher 有一些时间来连接。所以在 Connect/Bind 之后的一个简单的 System.Threading.Thread.Sleep(500); 就成功了。