ZeroMQ和本地FIFO

时间:2013-03-01 20:10:24

标签: zeromq

我有两个进程('发送方'和'接收方')需要通过瞬态单向FIFO通信管道进行通信,本地在一台机器上。这就是我想要发生的事情(使用更接近Unix域套接字的语言):

  • 发件人在众所周知的地址“创建”管道,并立即向其发送消息
  • 在某些时候(发件人“创建”管道之前或之后),接收器连接到管道
  • Reader从管道中读取消息
  • 发件人“关闭”管道
  • Reader注意到所有消息都已被读取(可能是管道已关闭)

我的问题是:如何使用ZeroMQ实现这一点? “PUB / SUB”,“PUSH / PULL”?在ZMQ套接字中检测“数据结束”的机制是什么?是否可以允许上述前两项的两个排序:即发送方或接收方是否首先尝试连接?如果是这样,怎么样?

感谢。

1 个答案:

答案 0 :(得分:5)

关于zeromq的事情:

  1. 绑定/连接顺序通常不重要
  2. 当一个对等方应接收每条消息和/或不应丢弃消息时使用PUSH / PULL
  3. PUB / SUB用于所有对等方都应该接收消息时发送的消息和/或消息,应该删除任何人。
  4. ZeroMQ故意隐藏应用程序代码中的连接/断开打开/关闭事件,因此您无法检测到实际的关闭事件。
  5. 您需要知道的一件事是,您不应该:当套接字连接时,它会创建一个管道(对等体尚不存在)。当套接字绑定时,它只在对等连接时创建管道。这些管道控制套接字的HWM行为。这意味着没有对等体的连接套接字和没有对等体的绑定套接字的行为是不同的。如果您尝试使用它发送消息,则没有对等体的绑定套接字将阻塞,而连接套接字将很乐意将消息排入内存中,直到对等体到达并开始使用消息。

    基于这些要点,您要做的是:

    1. 使用PUSH / PULL
    2. 接收器应绑定
    3. 发送一条特殊的“关闭”消息,指示队列已完成,而不是检测到tcp / ipc级关闭事件。
    4. 这是Python中的一个工作示例,它使用IPC套接字(文件)进行通信,接收者在发送者之后的某个时间开始。

      双方需要知道的共同信息:

      import time
      
      import zmq
      
      # the file used for IPC communication
      PIPE = '/tmp/fifo-pipe'
      
      # command flags for our tiny message protocol
      DONE = b'\x00'
      MSG = b'\x01'
      

      接收器(PULL)绑定,消耗直到DONE

      def receiver():
          ctx = zmq.Context()
          s = ctx.socket(zmq.PULL)
          s.bind("ipc://%s" % PIPE)
          while True:
              parts = s.recv_multipart()
              cmd = parts[0]
              if cmd == DONE:
                  print "[R] received DONE"
                  break
              msg = parts[1]
              # handle the message
              print "[R] %.1f consuming %s" % (time.time() - t0, msg)
          s.close()
          ctx.term()
          print "[R] done"
      

      发送方(PUSH)连接并发送DONE信号完成

      def sender():
          ctx = zmq.Context()
          s = ctx.socket(zmq.PUSH)
          s.connect("ipc://%s" % PIPE)
      
          for i in range(10):
              msg = b'msg %i' % i
              print "[S] %.1f sending %s" % (time.time() - t0, msg)
              s.send_multipart([MSG, msg])
              time.sleep(1)
          print "[S] sending DONE"
          s.send(DONE)
          s.close()
          ctx.term()
          print "[S] done"
      

      和一个演示脚本一起运行它们,发送者首先开始,接收者在发送者已经发送了几条消息之后开始:

      from threading import Thread
      
      # global t0, just for keeping times relative to start, rather than 1970
      t0 = time.time()
      
      # start the sender
      s = Thread(target=sender)
      s.start()
      
      # start the receiver after a delay
      time.sleep(5)
      r = Thread(target=receiver)
      r.start()
      
      # wait for them both to finish
      s.join()
      r.join()
      

      可以看到一起运行here