Python zmq SUB 套接字未接收 MQL5 Zmq PUB 套接字

Posted

技术标签:

【中文标题】Python zmq SUB 套接字未接收 MQL5 Zmq PUB 套接字【英文标题】:MQL5 Zmq PUB socket not being received by Python zmq SUB socket 【发布时间】:2018-11-29 22:33:19 【问题描述】:

我正在尝试在 MQL5 中设置一个 PUB 套接字,并在 Python 中设置一个将接收消息的 SUB 套接字。

我在 MQL5 中有这个:

#include <Zmq/Zmq.mqh>

Context context("helloworld");
Socket socket(context,ZMQ_PUB);

string BROKER;

int OnInit()

   if (socket.bind("tcp://*:5556"))
   
       Print("Error");
   
   else
       Print("Bound");
   BROKER = AccountInfoString(ACCOUNT_COMPANY);
   return(INIT_SUCCEEDED);


void OnTick()
  
   MqlTick last_tick; 
   string str;
   if(SymbolInfoTick(Symbol(),last_tick)) 
    
      StringConcatenate(str, BROKER, ",", Symbol(), ",", last_tick.time_msc, ",", last_tick.ask, ",", last_tick.bid, ",", last_tick.last, ",", last_tick.volume); 
    
   else 
      str = "FAIL";

   Print(str);
   ZmqMsg reply(str);
   socket.send(reply);

这在 Python 中:

import zmq
import random
import sys
import time

context = zmq.Context()
socket = context.socket(zmq.SUB)

ports = [5556]
for port in ports:
    print(port)
    socket.connect("tcp://localhost:".format(port))
socket.setsockopt_string(zmq.SUBSCRIBE, '')

print('connected')

f = open('metatrader-1.csv', 'a')
while True:
    msg = socket.recv()
    print(msg)
    f.write(str(msg) + '\n')

这个问题是这似乎在 Python 端没有收到任何东西,recv 调用只是永远阻塞。 OnTick 方法在 MT 中触发,因为可以看到打印。

我怎样才能让它工作?

请注意,如果我切换到 REP/REQ 对,它会起作用。

MQL5:

#include <Zmq/Zmq.mqh>


Context context("helloworld");
Socket socket(context,ZMQ_REQ);

string BROKER;

int OnInit()

   if (socket.connect("tcp://localhost:5555"))
   
      Print("Error");
   
   else
      Print("Bound");
   BROKER = AccountInfoString(ACCOUNT_COMPANY);
   return(INIT_SUCCEEDED);


void OnTick()
  
   MqlTick last_tick; 
   string str;
   if(SymbolInfoTick(Symbol(),last_tick)) 
    
      StringConcatenate(str, BROKER, ",", Symbol(), ",", last_tick.time_msc, ",", last_tick.ask, ",", last_tick.bid, ",", last_tick.last, ",", last_tick.volume); 
    
   else 
      str = "FAIL";

   Print(str);
   ZmqMsg reply(str);
   socket.send(reply);
   socket.recv(reply);

Python:

import zmq
import random
import sys
import time

context = zmq.Context()
socket = context.socket(zmq.REP)

ports = [5555]
for port in ports:
    print(port)
    socket.bind("tcp://*:".format(port))
#socket.setsockopt_string(zmq.SUBSCRIBE, '')

print('connected')

f = open('metatrader-1.csv', 'a')
while True:
    msg = socket.recv()
    socket.send_string('ack')
    print(msg)
    f.write(str(msg) + '\n')

但这有一些缺点,所以如果我能帮上忙,我宁愿不使用它。

【问题讨论】:

【参考方案1】:

您的套接字选项必须放在套接字连接之前,因此您的代码将是:

import zmq
import random
import sys
import time

context = zmq.Context()
socket = context.socket(zmq.SUB)

ports = [5556]
socket.setsockopt(zmq.SUBSCRIBE, b"")  # Note.

for port in ports:
    print(port)
    socket.connect("tcp://localhost:".format(port))

print('connected')

f = open('metatrader-1.csv', 'a')
while True:
    msg = socket.recv()
    print(msg)
    f.write(str(msg) + '\n')

另外,这部分:

if (socket.bind("tcp://*:5556"))

   Print("Error");

else
   Print("Bound");

应该反过来。当套接字成功绑定时,这实际上会打印一个错误。

【讨论】:

这是有道理的,但是即使这样,行为仍然保持不变。 您是否使用socket.setsockopt(zmq.SUBSCRIBE, b"") 而不是socket.setsockopt_string(zmq.SUBSCRIBE, '') 进行测试? 是的,我就是这么用的。 Python 端没有收到任何内容。 事实证明,我在 MQL 端对绑定的错误检查是错误的,所以当实际出现错误时它会打印“Bound”,反之亦然(当我看到它打印错误时,我是我猜想阻止它太快了)。 setsockopt_string 也可以。我将接受这一点,并对错误检查进行编辑 - 我希望你不介意。 另请注意,如果端口被其他东西使用,通常会出现错误 - 在我的情况下,5556 不起作用,但 5555 起作用。

以上是关于Python zmq SUB 套接字未接收 MQL5 Zmq PUB 套接字的主要内容,如果未能解决你的问题,请参考以下文章

ZeroMQ 反转 PUB/SUB 的问题

ZMQ 套接字不是线程安全的,但我可以在不同的线程中使用 zmq_send() 和 zmq_recv() 吗?

zmq 交换和 HWM

ZMQ 套接字连接超时

ZMQ Python PUB/SUB 有效,但我的 C++ 订阅者与 Python Publisher 无效

ZMQ:socket_send/recv 阻塞