【问题标题】:MQL5 Zmq PUB socket not being received by Python zmq SUB socketPython zmq SUB 套接字未接收 MQL5 Zmq PUB 套接字
【发布时间】:2023-03-23 11:57:01
【问题描述】:

我正在尝试在 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')

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

【问题讨论】:

    标签: python python-3.x zeromq pyzmq mql5


    【解决方案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 起作用。
    猜你喜欢
    • 2022-11-19
    • 1970-01-01
    • 2018-11-26
    • 1970-01-01
    • 2015-08-26
    • 1970-01-01
    • 2018-01-15
    • 2012-09-14
    相关资源
    最近更新 更多