使用 ZEROMQ 和 NORM 将数据包多播到大量 WiFi 设备

Posted

技术标签:

【中文标题】使用 ZEROMQ 和 NORM 将数据包多播到大量 WiFi 设备【英文标题】:Using ZEROMQ and NORM to multicast packets to a large number of WiFI devices 【发布时间】:2015-03-17 18:47:43 【问题描述】:

我正在尝试使用 ZeroMQ 和 NORM 协议通过无线网络发送文件。我目前正在使用 PUB/SUB 模式,因为据我所知,这是 NORM 和 ZeroMQ 支持的唯一模式。

我已对其进行了设置,以便可以很好地传递小消息,但有时接收者不会收到消息。从那时起,消息就被丢弃了。有时可以通过重新启动发布服务器或订阅服务器来解决此问题,但并非每次都如此。我尝试调整发送的比特数和每次调用发送之间的时间无济于事。在连接变得不稳定之前,我似乎可以收到大约 20-60 条多播消息。如果我使用相同的代码但使用 TCP 进行设置,则连接更加可靠,在发生错误之前大约有数千条消息。

我已经尝试实现一个包装类来在一段时间不活动后重新启动订阅者 - 这没有奏效。在 while 循环内设置 socket.recv(zmq.NOBLOCK) 也不行。

我知道这里描述的 Pub-Sub 同步模式 http://zguide.zeromq.org/page:all#Node-Coordination,但是在 ZeroMQ 的 norm_engine.cpp (https://github.com/zeromq/libzmq/blob/master/src/norm_engine.cpp) 中实现的 NORM 看起来并没有设置为允许这种模式.

有没有办法重新发送丢失的数据包,或确保健康的多播连接?

代码是 Python。

出版商:

import zmq
import time
import os
context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.connect("norm://224.0.0.1:3000")
i = 1

imgfile_path = "/home/adam/programs/zmq/tux.svg.png"
imgsize = os.stat(imgfile_path).st_size
print "attempting to send", imgsize, "bytes"

sleep_time = 1
topic = ""
packet_size = 500
left = packet_size
f = open(imgfile_path, 'rb')
fi = f.read(packet_size)
while (imgsize - left) > packet_size:
    print "sent packet number:", i
    print "size: ", len(topic + str(i)[-1] + fi)
    i += 1
    socket.send(topic + str(i)[-1] + fi)

    fi = f.read(packet_size)
    left += packet_size
    time.sleep(sleep_time)
print imgsize, left
time.sleep(sleep_time)
fi = f.read(imgsize - left)
print fi
socket.send(topic + " " + fi)
f.close()

订阅者:

import zmq
context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.bind("norm://224.0.0.2:3000")
socket.setsockopt(zmq.SUBSCRIBE, "")

imgdir = "/home/adam/programs/zmq/img/"
filename = "tux.svg.png"
destfile = imgdir + filename
packet_size = 501
print "attempting to receive"
f = open(destfile, 'wb')
while True:
    msg = None
    while msg is None:
        try:
            msg = socket.recv(zmq.NOBLOCK)
        except:
            pass
    if msg: 
        print "msg = ", msg[0]
        print "we got something", len(msg)
        f.write(msg[1:])
        if len(msg) < packet_size:
            break
f.close()
print "exiting..."

此外,一旦我可以确保我可以发送文件,我想调整前向纠错和 NACK 率,这就是 NORM 对我如此有用的原因。有没有办法在不重写 norm_engine.cpp 的情况下做到这一点?

谢谢!

【问题讨论】:

【参考方案1】:

您假设的某些内容已在文档页面here 上得到确认。也就是说,目前它只是 PUB/SUB,尽管您确实有能力通过使用 PUB/SUB 的 NORM 和 REQ/REP 的 TCP 来进行链接的同步。

否则,我相信您在 NORM 实施阶段仍然处于相当早的阶段,因为(也来自我的链接)它谈到了所有尚未完成的事情。那是一年前的事了,但从那时起我就没有看到太多关于它的话题了。

根据您的基础架构的具体情况,多播可能甚至不是最佳选择,正如 here 所讨论的那样,没有任何多播协议是真正为当今的高性能网络速度而设计的。可能是您的实现正成为这些传输协议的自然结果而导致问题恢复不佳的受害者。

编辑:

根据您帖子中的 github 链接,代码自 2014 年 3 月 19 日以来一直没有更新,与我上面链接的页面发布的同一日期,所以它所说的关于 ZMQ 中的 NORM 传输的任何内容都应该完全正常- 迄今为止。

在页面底部,关于 ZMQ NORM 实现可以做什么和不能做什么的要点:

    当前的“norm_engine”采用了相当具体的 NORM 传输选项形式。可能需要通过 ZeroMQ API 公开额外的 NORM 特性和传输模式。一些例子包括: NORM 能够为应用程序交替提供类似于 UDP 的“尽力而为”和“优于尽力而为”(使用数据包擦除编码)交付服务。这将包括对 NORM FEC 编码参数的控制。

因此,看起来它(在当前状态下)无法让您对前向纠错进行任何控制,只是在其默认的反应性(高性能)状态下使用它。默认情况下,这应该为您的连接提供可靠性,但是如果 ZMQs 实现没有彻底完成它的步伐,它可能比您想要的更脆弱。由于缺乏内容和补丁,我认为它还没有为你准备好。

【讨论】:

谢谢。我正在尝试突破多播的界限,并认为可以通过这种方式传输数据。希望使用 NORM 的前向纠错来缓解速度问题。你听说过这样的事吗? 用 FEC 的更多细节更新了我的答案

以上是关于使用 ZEROMQ 和 NORM 将数据包多播到大量 WiFi 设备的主要内容,如果未能解决你的问题,请参考以下文章

ZeroMQ/NanoMsg 发布/订阅与多播

如何分析多播消息流?

RxJS主题(Subject)

如何使用 Flash 实现 Comet

组播到多个网卡

网络编程之多播