You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Python与MQL4通过ZMQ传输实时数据时的无限循环及接收失败问题

解决Python与MQL4通过ZMQ实时数据传输的死锁问题

我来帮你排查这个问题——你遇到的无限循环和收不到数据的核心原因是没有遵守ZMQ REQ-REP模式的通信规则,咱们一步步理清楚:

核心问题:REQ-REP模式的通信顺序错误

ZMQ的REQ(请求端)和REP(响应端)套接字有严格的交互规则:

  • REQ套接字必须先发送请求,才能等待接收响应
  • REP套接字必须先接收请求,才能发送响应

你的代码完全搞反了这个顺序:Python端一直卡在recv()等待响应,但从来没发过请求;MQL4端直接send()响应,但从来没接收过请求,两边互相等待,形成了死锁。


修正后的Python代码(REQ客户端)

下面是符合REQ模式的代码,先发送请求再接收响应,如果需要持续实时交互,可以加循环控制:

单次请求版本

import zmq

port = "5555"
print("Connecting to MQL4 server…")
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect(f"tcp://localhost:{port}")

try:
    # REQ模式必须先发送请求
    socket.send_string("Request latest market data")
    print("Sent request to MQL4, waiting for response...")
    
    # 接收MQL4的响应
    message = socket.recv_string()
    print(f"Received from MQL4: {message}")
except zmq.ZMQError as e:
    print(f"ZMQ Error occurred: {e}")
finally:
    # 清理资源
    socket.close()
    context.term()

持续实时请求版本

import zmq
import time

port = "5555"
print("Connecting to MQL4 server…")
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect(f"tcp://localhost:{port}")

try:
    while True:
        # 每次循环先发送请求
        socket.send_string("Get real-time data")
        print("Sent request, waiting for response...")
        
        # 接收响应
        message = socket.recv_string()
        print(f"Real-time data: {message}")
        
        # 控制请求频率,避免过度占用资源
        time.sleep(1)
except KeyboardInterrupt:
    print("Stopping Python client...")
finally:
    socket.close()
    context.term()

修正后的MQL4代码(REP服务端)

MQL4是事件驱动架构,代码要放在OnInit、OnTick等事件函数里,同时必须先接收请求再发送响应:

#include <Zmq/Zmq.mqh>

Context context("mt4-python-connector");
Socket socket(context, ZMQ_REP);
bool socketBound = false;

// 初始化时绑定端口
int OnInit()
{
    if(!socket.bind("tcp://*:5555"))
    {
        Print("Failed to bind socket: ", ZmqLastError());
        return(INIT_FAILED);
    }
    socketBound = true;
    Print("Socket bound to tcp://*:5555, waiting for Python requests...");
    return(INIT_SUCCEEDED);
}

// 卸载时清理资源
void OnDeinit(const int reason)
{
    if(socketBound)
    {
        socket.close();
        context.term();
    }
}

// 每次行情Tick触发时检查并处理请求
void OnTick()
{
    if(!socketBound) return;
    
    ZmqMsg request;
    // 用非阻塞接收,避免阻塞OnTick事件
    if(socket.recv(request, ZMQ_DONTWAIT))
    {
        Print("Received request from Python: ", request.toString());
        
        // 准备响应数据,比如当前货币对的买价
        string replyContent = StringFormat("EURUSD Bid Price: %.5f", Bid);
        ZmqMsg reply(replyContent);
        
        if(!socket.send(reply))
        {
            Print("Failed to send reply: ", ZmqLastError());
        }
        else
        {
            Print("Sent reply to Python: ", replyContent);
        }
    }
}

额外注意事项

  1. 运行顺序:必须先启动MQL4的EA/脚本(让它绑定端口并等待请求),再启动Python客户端
  2. ZMQ库兼容性:确保MQL4的ZMQ库放在MT4安装目录/MQL4/Include/Zmq下,且版本与你的MT4版本匹配
  3. 实时推送场景优化:如果需要MQL4主动向Python推送实时数据(无需请求响应),更适合用ZMQ的PUB-SUB(发布-订阅)模式,这种模式不需要严格的请求响应顺序,更适合实时数据流传输

内容的提问来源于stack exchange,提问作者Kemal Bayram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 15:42:38