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

ZeroMQ中能否获取发布者与订阅者的身份及IP地址?

ZeroMQ PUB-SUB模式下获取对方IP的解决方案

好问题!我刚好在ZeroMQ相关的项目里处理过类似的需求,咱们把这两个问题拆开来一步步说清楚:

发布者能否获取所有订阅者的IP?

首先明确:ZeroMQ原生的PUB-SUB模式里,发布者默认是拿不到订阅者的IP地址的。因为ZeroMQ的设计理念是封装底层网络细节,PUB套接字只负责发送消息,不会主动追踪连接过来的订阅者信息。

但要实现这个需求也不难,咱们可以通过「订阅者主动上报」的方式来搞定:

  • 订阅者在完成主题订阅后,通过一个额外的通信通道(比如单独的PUSH-PULL套接字对)向发布者发送自己的IP地址
  • 发布者维护一个集合来存储所有上报的订阅者IP,这样就能实现追踪和展示的效果

举个简单的Python伪代码示例,方便你理解:

发布者端代码片段

import zmq
import time

context = zmq.Context()

# 用于发布业务消息的PUB套接字
pub_socket = context.socket(zmq.PUB)
pub_socket.bind("tcp://*:5555")

# 用于接收订阅者IP上报的PULL套接字
pull_socket = context.socket(zmq.PULL)
pull_socket.bind("tcp://*:5556")

# 存储已注册的订阅者IP
subscribers = set()

while True:
    # 非阻塞接收订阅者的IP上报
    try:
        sub_ip = pull_socket.recv_string(flags=zmq.NOBLOCK)
        if sub_ip not in subscribers:
            subscribers.add(sub_ip)
            print(f"新增订阅者(主题'foo'): {sub_ip}")
    except zmq.Again:
        pass

    # 正常发布业务消息
    pub_socket.send_string("foo: 这是一条测试消息")
    time.sleep(1)

订阅者端代码片段

import zmq
import socket

context = zmq.Context()

# 订阅业务消息的SUB套接字
sub_socket = context.socket(zmq.SUB)
sub_socket.connect("tcp://192.168.1.1:5555")
sub_socket.setsockopt_string(zmq.SUBSCRIBE, "foo")

# 获取本地对外的IP地址(适配不同网络场景)
def get_local_public_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        # 连接公共DNS服务器来获取当前出口IP
        s.connect(("8.8.8.8", 80))
        local_ip = s.getsockname()[0]
    finally:
        s.close()
    return local_ip

# 向发布者上报自身IP的PUSH套接字
push_socket = context.socket(zmq.PUSH)
push_socket.connect("tcp://192.168.1.1:5556")
push_socket.send_string(get_local_public_ip())

# 接收发布者的业务消息
while True:
    msg = sub_socket.recv_string()
    print(f"收到消息: {msg}")

订阅者能否获取发布者的IP?

这个就简单多了!订阅者完全可以获取发布者的IP地址,有两种常用方式:

  1. 直接使用你在connect方法里硬编码的发布者地址(毕竟是你主动连过去的,肯定知道目标IP)
  2. 通过ZeroMQ的套接字选项,动态获取实际连接的对等方地址(适合动态配置发布者地址的场景)

比如用第二种方式的Python代码示例:

import zmq

context = zmq.Context()
sub_socket = context.socket(zmq.SUB)
sub_socket.connect("tcp://192.168.1.1:5555")
sub_socket.setsockopt_string(zmq.SUBSCRIBE, "foo")

# 获取最后一次连接的发布者端点信息
peer_endpoint = sub_socket.getsockopt_string(zmq.LAST_ENDPOINT)
# 从端点字符串中提取IP地址
pub_ip = peer_endpoint.split("://")[1].split(":")[0]

print(f"当前连接的发布者(主题'foo'): {pub_ip}")

需要注意的是,如果订阅者同时连接了多个发布者,LAST_ENDPOINT只会返回最后一次连接的地址,这种情况下你需要自己维护每个发布者的连接信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:18:09