2016-10-04 2 views
1

У меня есть два простых компонента, которые должны взаимодействовать друг с другом с использованием шаблона REQ/REP ZeroMQ. Сервер (РЭП гнездо) осуществляется в Python с помощью pyzmq:ZeroMQ FiniteStateMachineException в шаблоне REQ/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() 
      print "EOM\n\n" 

Клиент (REQ сокет), написанный в C# с использованием библиотеки NetMQ:

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); 
     } 
    } 
} 
реализация

Питон сервера была испытана и отлично работает, разговаривая с гнездом REQ, реализованным с использованием Python. Но # REQ разъем C выдает следующее сообщение об ошибке в первой итерации цикла и никаких сообщений не достигнет сервера вообще:

Необработанное исключение типа «NetMQ.FiniteStateMachineException» произошло в NetMQ.dll Дополнительная информация: Req. XSend - не может отправить еще один запрос

StackTrace:

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 в своем ответе, казненным было то, что обе сокеты должны пройти полный цикл отправки/приема, прежде чем их можно будет повторно использовать. На самом деле сокет REP, реализованный в python, никогда не изменял его состояние, так что ошибка была в обоих, в коде 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

запроса и ответа сокеты автоматы с Запроса вы должны сначала Отправить, а затем вызвать Receive, вы не можете назвать 5 последовательных отправлений.

С ответом на свое противоположное, вы должны позвонить Получать первым.

Если одна сторона отправляет только одну, а другую только получая, вы можете использовать шаблон Push-Pull вместо Req-Rep. Вы также можете использовать Dealer-Router, если необходимо, в обоих направлениях общения. В любом случае, использование Req-Rep неверно.

+0

Спасибо @somdoron! Это было! Я не знал о концепции конечной машины. Будет добавлен исправленный код в тело вопроса. – EmEs

Смежные вопросы