2016-10-04 56 views
1

我有两个简单的组件,它们应该使用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); 
      } 
     } 
    } 
} 

回答

2

Request和Response套接字状态机,与要求必须先发,然后调用接收,你不能打电话连续发送5次。

With Response与此相反,必须先调用Receive。

如果一方只发送,另一方只接收,您可以使用Push-Pull模式而不是Req-Rep。如果需要双向沟通,您也可以使用Dealer-Router。无论如何,似乎Req-Rep的用法是不正确的。

+0

谢谢@somdoron!就是这样!我没有意识到有限状态机的概念。将修正后的代码添加到问题的正文中。 – EmEs