与0mq通信

时间:2014-12-12 12:17:57

标签: python zeromq

我正在尝试创建一个收集发送数据的系统 我有两个小脚本,一个应该接收数据的receiver.py,以及应该发送它的发送者,我尝试使用1-1连接的那一刻,但最后我需要多个发送器和一个接收器来处理传入数据。我尝试使用0mq发布者/订阅者模式来完成此任务。

#receiver.py

def receive():
    context = zmq.Context()
    socket = context.socket(zmq.SUB)
    socket.setsockopt(zmq.SUBSCRIBE, 'Child:') 
    socket.bind('tcp://localhost:5000')
    while True:
        print 'Parent received: %s' % socket.recv()

receive()

#sender.py

def send(data):
    context = zmq.Context()
    socket = context.socket(zmq.PUB)
    socket.connect('tcp://localhost:5000')
    socket.send('Sender: %i' % data)
    socket.close()
    print "sent"

send(10)

当我启动receiver.py时它只是等待数据,当我运行sender.py时没有收到任何内容。我很感激建议,实际上我甚至不确定发布者/订阅者是否是我的场景的最佳模式(多个传感器通过本地网络将数据发送到一台服务器进行实时处理)。

2 个答案:

答案 0 :(得分:2)

为了理解发生了什么,我改写了它:

import zmq
import threading
import time

def receive():
    context = zmq.Context()
    socket = context.socket(zmq.SUB)
    socket.bind("tcp://127.0.0.1:5000")
    socket.setsockopt(zmq.SUBSCRIBE, '')
    while True:
        print 'Parent received: %s' % socket.recv()

threading.Thread(target=receive).start()

def send(data):
    context = zmq.Context()
    socket = context.socket(zmq.PUB)
    socket.connect("tcp://localhost:5000")
    while data:
        socket.send('Sender: %i' % data)
        data -= 1
        time.sleep(1)

输出:

>>> send(10)
Parent received: Sender: 9
Parent received: Sender: 8
Parent received: Sender: 7
Parent received: Sender: 6
Parent received: Sender: 5
Parent received: Sender: 4
Parent received: Sender: 3
Parent received: Sender: 2
Parent received: Sender: 1

关键点是:

  1. Why doesn't zeromq work on localhost?中所述,您必须使用127.0.0.1来绑定您的localhost
  2. 发布商未公开名称,因此我们必须从订阅者中移除Child:或将其更改为Sender:或在{{1}中更改send() Sender: (我已经选择了第一个)
  3. 也许你需要某种事件,说发送数据之前订阅者的连接是活动的(zeromq是一个异步框架),否则你会丢失第一条消息。作为证据,您可以更改Child:,例如以下示例,但您不会丢失任何消息。
  4. send()

    输出:

    def send(data):
        context = zmq.Context()
        socket = context.socket(zmq.PUB)
        socket.connect("tcp://localhost:5000")
        while data:
            time.sleep(1)
            socket.send('Sender: %i' % data)
            data -= 1
        socket.close()
    

答案 1 :(得分:1)

如果您无法让示例正常运行,则表明您的ZMQ库安装有问题,或者您的库版本与您的库版本不兼容,这是一个好兆头。绑定你的使用。在那里开始检查,并始终首先尝试逐字运行示例,以确保所有内容至少与参考代码一起使用。

但是,我确实看到您的代码中至少有一个问题会导致您永远不会收到消息。

在您的订阅者中,您订阅了“孩子:'”,但在您的发布商中,您永远不会发送与之匹配的消息。 "正确"这样做的方法是发送一个多帧消息,但为了简化代码,您还可以发送一个以您的主题开头的字符串,如下所示:

socket.send('Child: Sender: %i' % data)

或者,您可以更改订阅者以适合当前的消息模式:

socket.setsockopt(zmq.SUBSCRIBE, 'Sender:')

最后但并非最不重要的是,如果您想订阅发布商可能发送的所有内容,您可以订阅空字符串:

socket.setsockopt(zmq.SUBSCRIBE, '')

......这最后一个可能对你的情况是正确的。因此,结果代码如下:

#receiver.py

def receive():
    context = zmq.Context()
    socket = context.socket(zmq.SUB)
    socket.setsockopt(zmq.SUBSCRIBE, '') 
    socket.bind('tcp://localhost:5000')
    while True:
        print 'Parent received: %s' % socket.recv()

receive()

#sender.py

def send(data):
    context = zmq.Context()
    socket = context.socket(zmq.PUB)
    socket.connect('tcp://localhost:5000')
    socket.send('Sender: %i' % data)
    socket.close()
    print "sent"

send(10)

解决分点,问题和评论:

  • 在这种情况下,对bind()的订阅者和connect()的发布者更合适(因为您已经完成),ZMQ并不关心您仅基于套接字类型使用。您的订阅者是您的服务器",您的发布商是您的客户",因此SUB应bind(),PUB应为connect()
  • PUB / SUB对于您的场景来说是一个很好的模式,只要您的情况下通信严格单向,它就会很好。