繁体   English   中英

如何在ZeroMQ中进行扇出? 从一组主题转发到多个客户端

[英]How to do fan-out in ZeroMQ? Forwarding from a set of topics to multiple clients

我需要实现一个服务器,该服务器通过控制通道(req-rep)接收指定一组主题的请求,然后作为响应发送指向将为此特定客户端打开的发布者套接字的URL 拒绝消息(因为权限不足)。

我设法实现了一次只能处理一个客户端的版本(带有两个无限循环),但是我不知道该使用哪种模式来同时处理多个客户端。

对我来说重要的是,不同客户端的套接字必须保持独立。

这是简化的代码:

import zmq

context = zmq.Context()

upstream_port = 10000
upstream_host = 'localhost'
control_channel_port = 11000
upstream_addr = 'tcp://{}:{}'.format(upstream_host, upstream_port)

def should_grant(request):
    '''
    Permission checking - irrelevant to the question
    '''
    return True


def bind_downstream():
    downstream = context.socket(zmq.PUB)
    addr = 'tcp://*'
    port = downstream.bind_to_random_port(addr)
    return downstream, port


def bind_control_channel():
    control_channel_sock = context.socket(zmq.REP)
    control_channel_sock.bind('tcp://*:{}'.format(control_channel_port))
    return control_channel_sock


def connect_upstream(topics):
    raw_data = context.socket(zmq.SUB)
    for t in topics:
        raw_data.setsockopt_unicode(zmq.SUBSCRIBE, unicode(t))
    raw_data.connect(upstream_addr)
    return raw_data


if __name__ == '__main__':
    print("Binding control channel socket on {}".format('tcp://*:{}'.format(control_channel_port)))
    control_channel = bind_control_channel()
    while True:
        request = control_channel.recv_json()
        print("Received request {}".format(request))
        if should_grant(request):
            (downstream_sock, downstream_port) = bind_downstream()
            print("Downstream socket open on {}".format('tcp://*:{}'.format(downstream_port)))

            print("Connecting to upstream on {}".format(upstream_addr))
            upstream_sock = connect_upstream(request['topics'])

            control_channel.send_json({'status': 'ok', 'port': downstream_port})
            while True:
                parts = upstream_sock.recv_multipart() # Simple forwarding
                downstream_sock.send_multipart(parts)
        else:
            control_channel.send_json({'status': 'rejected'})

正确的方法是使用线程。

您的主程序或线程将处理控制通道循环。 一旦出现连接,就可以创建上游和下游套接字,但是可以在线程中处理实际的传输。 我不确定下面的代码是否可以正常工作,因为我没有可以使用它的客户端,但是可以试一下看看会发生什么。 尽管如此,您会明白的。

from threading import Thread
....
....
class ClientManager(Thread):
    def __init__(self, ups, downs):
        super(ClientManager, self).__init__(self)
        self.upstream_socket = ups
        self.downstream_socket = downs

    def run(self):
        while True:
            _parts = self.upstream_socket.recv_multipart()
            self.downstream_socket.send_multipart(_parts)

if __name__ == '__main__':
    print("Binding control channel socket on {}".format('tcp://*:{}'.format(control_channel_port)))
    control_channel = bind_control_channel()
    while True:
        request = control_channel.recv_json()
        print("Received request {}".format(request))
        if should_grant(request):
            (downstream_sock, downstream_port) = bind_downstream()
            print("Downstream socket open on {}".format('tcp://*:{}'.format(downstream_port)))

            print("Connecting to upstream on {}".format(upstream_addr))
            upstream_sock = connect_upstream(request['topics'])

            control_channel.send_json({'status': 'ok', 'port': downstream_port})
            _nct = ClientManager(upstream_sock, downstream_sock)
            _nct.daemon = True
            _nct.start()
    else:
        control_channel.send_json({'status': 'rejected'})

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM