Python pyzmq同时发送到多个客户端

Python pyzmq同时发送到多个客户端,python,networking,raspberry-pi,pyzmq,Python,Networking,Raspberry Pi,Pyzmq,我有一个Raspberry Pi客户端和4个Raspberry Pi服务器。我希望客户端同时向所有4台服务器发送字符串消息以捕获图像。现在,我正在按顺序使用如下内容 socket.send(capture) socket1.send(capture) socket2.send(capture) socket3.send(capture) 更改为类似于发布/订阅模式会提高客户端接收消息的距离吗?我希望4个客户端在5毫秒或更短的时间内收到捕获消息。欢迎来到Zen of Zero: 虽然我们获得零保

我有一个Raspberry Pi客户端和4个Raspberry Pi服务器。我希望客户端同时向所有4台服务器发送字符串消息以捕获图像。现在,我正在按顺序使用如下内容

socket.send(capture)
socket1.send(capture)
socket2.send(capture)
socket3.send(capture)
更改为类似于发布/订阅模式会提高客户端接收消息的距离吗?我希望4个客户端在5毫秒或更短的时间内收到捕获消息。

欢迎来到Zen of Zero: 虽然我们获得零保修,但我们可能会在适当的方向上采取一些措施。如果您是ZeroMQ新手,请在深入了解更多详细信息之前,随意阅读其中的一些内容,至少是“”:

客户端代码概念模板:
导入zmq;打印(zmq.zmq_version())#INF:
aCtx=zmq.Context(4)#请求4个I/O线程
aPUB=aCtx.socket(zmq.PUB)#PUB实例
aPUB.setsockopt(zmq.LINGER,0)#避免关闭时死锁
aPUB.setsockopt(zmq.SNDBUF,3*PayLoadSIZE)#全高清~6MB,4K~。。。
aPUB.setsockopt(zmq.SNDHWM,aNumOfPicsInQUEUE)#1,~3~10?, !1000 ...
aPUB.setsockopt(zmq.IMMEDIATE,1)#忽略L1/L2不完整
aPUB.setsockopt(zmq.CONFLATE,1)#不要重新发送“旧的”
aPUB.bind(:)#tcp:?udp多播?
#-----------------------------------------------------------------------------[RTO]
#可能需要设置aPayLOAD=gzip.compress(dill.dumps(capture),compressionLEVEL)
#减少了序列化数据的大小
#每侧的成本约为30~60[ms]
#这可能会降低网络流量和.SNDBUF大小问题
#----------------------------------------------------------------------
而:
尝试:
aPUB.send(aPayLOAD,zmq.NOBLOCK)
除:
#按照错误号处理。。。
最后:
通过
#----------------------------------------------------------------------
aPUB.close()
aCtx.术语()
服务器代码概念模板:
导入zmq;打印(zmq.zmq_version())#INF:
aCtx=zmq.Context()#请求4个I/O线程
aSUB=aCtx.socket(zmq.SUB)#子实例
aSUB.setsockopt(zmq.LINGER,0)#在关闭时避免死锁
aSUB.setsockopt(zmq.RCVBUF,3*PayLoadSIZE)#全高清~6MB,4K~。。。
aSUB.setsockopt(zmq.RCVHWM,aNumOfPicsInQUEUE)#1,~3~10?, !1000 ...
aSUB.setsockopt(zmq.IMMEDIATE,1)#忽略L1/L2不完整
aSUB.setsockopt(zmq.CONFLATE,1)#不重新记录“旧”
aSUB.setsockopt(zmq.SUBSCRIBE,“”)#请订阅任何内容
aSUB.connect(:)#tcp:?udp多播?
#-----------------------------------------------------------------------------[RTO]
而:
尝试:
如果(aSUB.poll(zmq.POLLIN,0)=0):
#接收队列中没有准备好发送到-.recv()的内容
#睡眠()
#做一些系统工作等
其他:
aPayLOAD=aSUB.recv(zmq.NOBLOCK)
#--------------------------------------------------------
#解压缩/反序列化原始对象
#capture=dill.load(gzip.decompress(aPayLOAD))
#--------------------------------------------------------
#处理数据:
# ...
除:
#按照错误号处理。。。
最后:
通过
#----------------------------------------------------------------------
aSUB.close()
aCtx.术语()

您可以使用发布/订阅模式。您的客户端将绑定到一个IP:端口,您的服务器将连接到客户端IP:端口,并为筛选器设置一个空字符串(请检查文档),然后客户端将发布一个字符串。此消息将同时发送到所有订阅的服务器。一旦服务器收到消息,他们就可以开始捕获过程。
zmq.COMPLETE
选项做什么?@BenyaminJafari Mea Culpa-代码输入得很匆忙,而且这个想法比我的输入技能快-正确的选项设置是
zmq.IMMEDIATE
模块常量,这可以防止将消息有效负载放入L1/L2不完整连接的队列(ZeroMQ ZMTP/RFC文档清楚地说明了状态完全连接管理的丰富程度),从而合理地避免了步骤上的任何延迟,这些步骤没有意义,可能会使到达

   import zmq;                 print( zmq.zmq_version() ) # INF:

   aCtx = zmq.Context( 4 )                                # request 4-I/O-threads
   aPUB = aCtx.socket( zmq.PUB )                          # PUB-instance
   aPUB.setsockopt(    zmq.LINGER,   0 )                  # avoid deadlock on close
   aPUB.setsockopt(    zmq.SNDBUF, 3 * PayLoadSIZE )      # FullHD ~ 6 MB, 4K ~ ...
   aPUB.setsockopt(    zmq.SNDHWM, aNumOfPicsInQUEUE )    # 1, ~3? ~10?, !1000 ...
   aPUB.setsockopt(    zmq.IMMEDIATE, 1 )                 # ignore L1/L2-incomplete(s)
   aPUB.setsockopt(    zmq.CONFLATE, 1 )                  # do not re-send "old"
   aPUB.bind( <transport-class>:<port#> )                 # tcp:? udp-multicast?
   #-----------------------------------------------------------------------------[RTO]
   # may like to set aPayLOAD = gzip.compress( dill.dumps( capture ), compressionLEVEL )
   #                 yields reduced sizes of the serialised <capture> data
   #                 at costs of about ~30~60 [ms] on either side
   #                 which may lower the network traffic and .SNDBUF-sizing issues
   #----------------------------------------------------------------------
   while <any reason>:
         try:
              aPUB.send( aPayLOAD, zmq.NOBLOCK )
         except:
              # handle as per errno ...
         finally:
              pass
   #----------------------------------------------------------------------
   aPUB.close()
   aCtx.term()
   import zmq;                 print( zmq.zmq_version() ) # INF:

   aCtx = zmq.Context()                                   # request 4-I/O-threads
   aSUB = aCtx.socket( zmq.SUB )                          # SUB-instance
   aSUB.setsockopt(    zmq.LINGER,   0 )                  # avoid deadlock on close
   aSUB.setsockopt(    zmq.RCVBUF, 3 * PayLoadSIZE )      # FullHD ~ 6 MB, 4K ~ ...
   aSUB.setsockopt(    zmq.RCVHWM, aNumOfPicsInQUEUE )    # 1, ~3? ~10?, !1000 ...
   aSUB.setsockopt(    zmq.IMMEDIATE, 1 )                 # ignore L1/L2-incomplete(s)
   aSUB.setsockopt(    zmq.CONFLATE, 1 )                  # do not re-recv "old"
   aSUB.setsockopt(    zmq.SUBSCRIBE, "" )                # do subscribe to whatever comes
   aSUB.connect( <transport-class>:<port#> )              # tcp:? udp-multicast?
   #-----------------------------------------------------------------------------[RTO]
   while <any reason>:
         try:
              if ( aSUB.poll( zmq.POLLIN, 0 ) == 0 ):
                 # nothing in the receiving Queue ready-to-.recv()
                 # sleep()
                 # do some system work etc
              else:
                 aPayLOAD = aSUB.recv( zmq.NOBLOCK )
                 #--------------------------------------------------------
                 # decompress / deserialise the original object
                 # capture = dill.loads( gzip.decompress( aPayLOAD ) )
                 #--------------------------------------------------------
                 # PROCESS THE DATA :
                 # ...
         except: 
              # handle as per errno ...
         finally:
              pass
   #----------------------------------------------------------------------
   aSUB.close()
   aCtx.term()