如何使用 pyzmq 进行 inproc 传输?

问题描述 投票:0回答:3

我已经设置了两个小脚本来模仿 pyzmq 的发布和订阅过程。但是,我无法使用

inproc
传输将消息发送到我的订阅者客户端。我可以很好地使用
tcp://127.0.0.1:8080
,只是不能在进程中使用。

pub_server.py

import zmq
import random
import sys
import time

context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("inproc://stream")

while True:
    socket.send_string("Hello")
    time.sleep(1)

sub_client.py

import sys
import zmq

# Socket to talk to server
context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.setsockopt_string(zmq.SUBSCRIBE, '')
socket.connect("inproc://stream")

for x in range (5):
    string = socket.recv()
    print(string)

如何成功更改代码,以便能够在两个脚本之间使用 inproc 传输方法?

编辑:

我已经更新了我的代码以进一步反映@larsks 评论。我仍然没有收到我发布的字符串 - 我做错了什么?

import threading
import zmq

def pub():
    context = zmq.Context()
    sender = context.socket(zmq.PUB)
    sender.connect("inproc://hello")
    lock = threading.RLock()

    with lock:
        sender.send(b"")

def sub():
    context = zmq.Context()
    receiver = context.socket(zmq.SUB)
    receiver.bind("inproc://hello")

    pub()

    # Wait for signal
    string = receiver.recv()
    print(string)
    print("Test successful!")

    receiver.close()

if __name__ == "__main__":
    sub()
python sockets publish-subscribe pyzmq inproc
3个回答
8
投票

顾名思义,

inproc
套接字只能在同一进程内使用。如果您要重写客户端和服务器,以便同一进程中有两个线程,您可以使用
inproc
,但否则此套接字类型根本不适合您正在做的事情。

文档在这一点上非常清楚:

进程内传输通过内存直接在共享单个 ØMQ 上下文的线程之间传递消息。

更新

查看更新后的代码,首先突出的问题是,虽然上面引用的文档说“...共享单个 ØMQ 上下文的线程之间”,但您正在代码中创建two上下文。通常,您只会在程序中调用

zmq.Context()
一次

接下来,您永远不会向订阅者订阅任何消息,因此即使其他一切正常工作,您实际上也不会收到任何消息。

最后,您的代码将遇到 缓慢的连接器问题

关于 PUB-SUB 套接字,需要了解一件更重要的事情:您无法准确知道订阅者何时开始获取消息。即使您启动订阅者,等待一段时间,然后启动发布者,订阅者也总是会错过发布者发送的第一条消息。这是因为当订阅者连接到发布者时(需要很短但非零的时间),发布者可能已经在发送消息了。

发布/订阅模型并不适用于单个消息,也不是一种可靠的传输。

所以,总结一下:

  • 在创建套接字之前,您需要创建一个共享的 ZMQ 上下文。
  • 您可能希望发布者循环发布而不是发布单个消息。由于您尝试使用
    inproc
    套接字,因此您需要将两个函数放入单独的线程中。
  • 您需要设置订阅过滤器才能接收消息。

ZMQ 文档中有一个使用 PAIR

 套接字
示例,可能会提供有用的起点。
PAIR
套接字旨在通过
inproc
套接字协调线程,与 pub/sub 套接字不同,它们是双向的,并且不受“慢连接器”问题的影响。


0
投票

正如@larsks 之前提到的,上下文对象应该是相同的。全局声明上下文对象并在 pub 和 sub 函数中使用它,而不是为每个函数创建新的。


0
投票

Zmq 上下文是使用 zmq 时唯一的线程安全数据类型,并且无论语言如何,使用 inproc 时都必须在线程之间共享公共上下文。这是因为 zmq 上下文实际上是 zmq 中 io 发生的地方,并且 inproc 套接字共享相同的事件循环,其中其他传输可能(并且经常会)使用单独的 io 循环。这是 python 多线程 inproc 的示例 http://zguide2.zeromq.org/py:mtrelay

另请注意,只要您不使用阻塞套接字类型,inproc 就可以在同一线程中

© www.soinside.com 2019 - 2024. All rights reserved.