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

如何为zmq::message_t赋值字符串?ZeroMQ发布订阅通信问题排查

问题分析与解决

核心问题点

  1. 订阅时机错误:发布者先发送消息,订阅者才设置订阅规则,ZeroMQ的PUB-SUB模式中,订阅者必须在消息发送前完成订阅,否则会直接错过消息。
  2. zmq::message_t直接打印无效:标准库未为zmq::message_t重载std::ostream的<<操作符,直接cout << message输出的是对象内存信息,并非消息内容,这导致你误以为消息为空。
  3. 字符串转zmq::message_t的冗余操作:无需手动memcpy,可以直接用字符串构造zmq::message_t,更简洁安全。

修正后的代码

#include <zmq.hpp>
#include <iostream>
#include <string>
#include <sstream>

int main()
{
    zmq::context_t context(1);

    zmq::socket_t pub(context, ZMQ_PUB);
    pub.bind("tcp://*:5555");
    std::cout << "Pub Connected" << std::endl;

    zmq::socket_t sub(context, ZMQ_SUB);    
    sub.connect("tcp://localhost:5555");
    // 先设置订阅规则(此处订阅所有消息,也可指定前缀如"Hello")
    sub.set(zmq::sockopt::subscribe, "");
    std::cout << "Sub Connected" << std::endl;

    // 给订阅者留时间完成连接握手,避免消息丢失
    zmq_sleep(1);

    std::stringstream s;
    s << "Hello World";
    auto ms = s.str();

    // 直接用字符串构造zmq::message_t,省去手动内存拷贝
    zmq::message_t message(ms.data(), ms.size());
    pub.send(message, zmq::send_flags::none);
    
    // 正确打印发送的消息内容
    std::string sent_str(static_cast<char*>(message.data()), message.size());
    std::cout << "Sent message: " << sent_str << std::endl;

    zmq::message_t rx_msg;
    sub.recv(rx_msg, zmq::recv_flags::none);

    std::string rx_str(static_cast<char*>(rx_msg.data()), rx_msg.size());
    std::cout << "Received message: " << rx_str << std::endl;

    return 0;
}

关键修正说明

  • 调整订阅顺序:将订阅规则设置移到消息发送前,同时添加zmq_sleep(1)确保订阅者与发布者完成连接握手,避免消息丢失。
  • 简化消息构造:使用zmq::message_t的内置构造函数直接传入字符串数据和长度,避免手动内存拷贝可能出现的错误。
  • 正确打印消息:通过message.data()提取字符指针,结合message.size()构造std::string后再打印,避免直接输出对象导致的误解。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 10:20:31