REQ/REP模式中的ZeroMQ FiniteStateMachineException
我有两个简单的组件,它们应该使用REQ/REP ZeroMQ模式相互通信。 服务器(REP插座)使用pyzmq用Python实现:REQ/REP模式中的ZeroMQ FiniteStateMachineException
import zmq
def launch_server():
print "Launching server"
with zmq.Context.instance() as ctx:
socket = ctx.socket(zmq.REP)
socket.bind('tcp://127.0.0.1:5555')
while True:
msg = socket.recv()
print "EOM\n\n"
客户(REQ插座)使用NetMQ库用C#编写:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NetMQ;
namespace PyNetMQTest
{
class Program
{
static void Main(string[] args)
{
string msg;
NetMQ.Sockets.RequestSocket socket = new NetMQ.Sockets.RequestSocket();
socket.Connect("tcp://127.0.0.1:5555");
for(int i=0; i<5; i++)
socket.SendFrame("test_"+i);
}
}
}
Python的服务器实施已经过测试,通过与使用Python实现的REQ套接字交谈可以很好地工作。但C#REQ插座引发以下错误的循环的第一次迭代中,并没有消息到达任何服务器:
类型的未处理的异常“NetMQ.FiniteStateMachineException”发生在NetMQ.dll 其他信息:所需物品。 XSEND - 不能发送另一个请求
堆栈跟踪:
at NetMQ.Core.Patterns.Req.XSend(Msg& msg)
at NetMQ.Core.SocketBase.TrySend(Msg& msg, TimeSpan timeout, Boolean more)
at NetMQ.NetMQSocket.TrySend(Msg& msg, TimeSpan timeout, Boolean more)
at NetMQ.OutgoingSocketExtensions.Send(IOutgoingSocket socket, Msg& msg, Boolean more)
at NetMQ.OutgoingSocketExtensions.SendFrame(IOutgoingSocket socket, String message, Boolean more)
at PyNetMQTest.Program.Main(String[] args) in d:\users\emes\documents\visual studio 2015\Projects\PyNetMQ Test\PyNetMQTest\Program.cs:line 20
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
这些是我第一次用ZMQ和C#代码的第一步是从图书馆documentation拍摄。 是什么让代码抛出这个错误?
我使用:
- pyzmq 14.7
- NetMQ 3.3.3.4
- .NET 4.6
========== ============解决方案======================
正如@somdoron在他的回答中所解释的那样,Roor casue认为两个套接字都需要在发送/接收完成之前完成,然后才能重用。 事实上,在python中实现的REP套接字并没有改变它的状态,所以错误出现在python和C#代码中。这里是固定的代码:
REP插槽
import zmq
def launch_server():
print "Launching server"
with zmq.Context.instance() as ctx:
socket = ctx.socket(zmq.REP)
socket.bind('tcp://127.0.0.1:5555')
while True:
msg = socket.recv()
socket.send("reply to "+msg)
print "EOM\n\n"
REQ插槽
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NetMQ;
namespace PyNetMQTest
{
class Program
{
static void Main(string[] args)
{
NetMQ.Sockets.RequestSocket socket = new NetMQ.Sockets.RequestSocket();
socket.Connect("tcp://127.0.0.1:5555");
string msg, reply;
while (true)
{
Console.WriteLine("Type message: ");
msg = Console.ReadLine();
Console.WriteLine("Sending : " + msg);
socket.SendFrame(msg);
reply = socket.ReceiveFrameString();
Console.WriteLine("Received: " + reply + Environment.NewLine);
}
}
}
}
Request和Response套接字状态机,与要求必须先发,然后调用接收,你不能打电话连续发送5次。
With Response与此相反,必须先调用Receive。
如果一方只发送,另一方只接收,您可以使用Push-Pull模式而不是Req-Rep。如果需要双向沟通,您也可以使用Dealer-Router。无论如何,似乎Req-Rep的用法是不正确的。
谢谢@somdoron!就是这样!我没有意识到有限状态机的概念。将修正后的代码添加到问题的正文中。 – EmEs