如何在 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。
我可以让两个应用程序通信,只要它们使用相同的语言
- c# 应用到 c# 应用;
- python -> python;
- java -> java,
但是当我尝试在不同语言之间进行连接时,麻烦就来了。
- java -> c# 和反向工作也很好 [edited]
我没有收到任何错误,但它也不起作用。
我首先尝试了 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);
就成功了。
我正在尝试通过 ZeroMQ 在 c#(5.0) 和 python (3.9) 应用程序之间进行通信。对于 .Net,我使用 NetMQ,对于 python PyZMQ。
我可以让两个应用程序通信,只要它们使用相同的语言
- c# 应用到 c# 应用;
- python -> python;
- java -> java,
但是当我尝试在不同语言之间进行连接时,麻烦就来了。
- java -> c# 和反向工作也很好 [edited]
我没有收到任何错误,但它也不起作用。
我首先尝试了 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);
就成功了。