[英]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.