ZMQ PUB发送文件

时间:2014-01-14 22:20:05

标签: python zeromq

我第一次尝试(PY)ZMQ,并想知道是否可以使用PUB / SUB发送完整的FILE(二进制)?我需要向许多订阅者发送数据库更新。我看到短消息的例子,但不是文件。有可能吗?

出版商:

import zmq
import time
import os
import sys

while True:

print 'loop'
msg = 'C:\TEMP\personnel.db'

# Prepare context & publisher
context = zmq.Context()
publisher = context.socket(zmq.PUB)
publisher.bind("tcp://*:2002")
time.sleep(1)

curFile = 'C:/TEMP/personnel.db'
size = os.stat(curFile).st_size
print 'File size:',size

target = open(curFile, 'rb')
file = target.read(size)
if file:
    publisher.send(file)

publisher.close()
context.term()
target.close()
time.sleep(10)

订户:

'''always listening'''

import zmq
import os
import time
import sys

while True:

path = 'C:/TEST'
filename = 'personnel.db'
destfile = path + '/' + filename

if os.path.isfile(destfile):
    os.remove(destfile)
    time.sleep(2)

context = zmq.Context()
subscriber = context.socket(zmq.SUB)
subscriber.connect("tcp://127.0.0.1:2002")
subscriber.setsockopt(zmq.SUBSCRIBE,'')

msg = subscriber.recv(313344)
if msg:
    f = open(destfile, 'wb')
    print 'open'
    f.write(msg)
    print 'close\n'
    f.close()

time.sleep(5)

1 个答案:

答案 0 :(得分:1)

您应该可以使用zmq和PUB / SUB模式将文件分发给许多订阅者。

您的代码几乎就在那里,换句话说,它可能在大多数情况下都可以使用,可以稍微改进一下。

要注意的事项

消息存在于内存中

消息在发布时(生活在PUB套接字中)必须适合内存,并保持在那里,直到最后一个当前订阅的消费者没有读出或断开连接。

收到消息时,消息也必须适合内存。但是对于合理的大文件(比如你的313 kB),它应该可以工作,除非你真的很短的RAM。

消费者问题缓慢

如果您有多个消费者,其中一个消费者的阅读速度比其他消费者慢得多,那么它将开始放慢所有消费者的速度。 Zmq正在解释这个问题,并提出了一些如何避免它的方法(例如,慢速用户的自杀)。

但是,在大多数情况下,您不会遇到此问题。

首先启动您的消费者不要错过消息

zmq消息传递非常快。没有问题,如果您尽早启动消费者,那么发布商zmq会使这种情况变得简单,消费者将自动连接。

但是,您的发布者应允许消费者在开始发布之前进行连接,您的代码在发送消息之前会进行1秒睡眠,这就足够了。

对代码的评论

  • 你是否真的要在os.remove之后睡觉?可能不是
  • subscriber.recv - 没有必要提前知道邮件大小,zmq数据包知道文件大小,所以如果你调用它而没有要接收的字节数,你就可以正常使用它。

以块的形式发送大文件

zmq提供了一个称为多部分消息的功能,但根据doc,它必须在发送之前完全适合(所有消息部分)在内存中,因此这不是使用的技巧。

另一方面,您可以通过这种方式创建“应用程序级多部分协议”,即您决定发送具有(hasNextPart,chunkData)结构的消息。通过这种方式,您可以发送控制良好的大小的消息,只有最后一个消息会告诉“hasNextPart”== False。

然后,消费者将读取并写入磁盘所有部分,直到最后一条消息,声称没有其他部分到达。