zeroMQ 订阅发布模式 小实例

目的

用python做一个方便使用的基于zeroMQ的订阅发布模式

代码

#socketSP.py
"as a subsriber  using zeromq"
import time
import zmq 
import sys 
class socketPub():
    def __init__(self, host, port): 
        self.host = host
        self.port = port
        self.context = zmq.Context()
    def __enter__(self):
        self.socket = self.context.socket(zmq.PUB)
        self.socket.bind("tcp://%s:%d"%(self.host, self.port))
        time.sleep(0.2)#再bind和send之间必须有一段延时, 否则可能会遗漏发送!!!!
        return self
    def __exit__(self, type, value, traceback):
        pass
        self.socket.close()
    def publish(self,string):  
        self.socket.send_string(string)
class socketSub():
    def __init__(self, targets):#targets means[(host1, port1), (host2, port2)], for multi-publish
        self.context = zmq.Context()
        self.targets = targets
    def __enter__(self):
        self.socket =  self.context.socket(zmq.SUB)
        for host, port in self.targets:
            self.socket.connect("tcp://%s:%d"%(host, port))
        self.socket.setsockopt_string(zmq.SUBSCRIBE, "")# 设置过滤选项, 此处不设置
        return self
    def __exit__(self, type, value, traceback):
        self.socket.close()
    def subscribe(self,times=sys.maxsize):
        for i in range(times):
            string = self.socket.recv()
            yield string.decode("utf-8")

#test.py
import unittest
import time
from socketSP import socketPub, socketSub
from multiprocessing import Process, Queue
host = "127.0.0.1"
port = 5556
class TestSocketPub(unittest.TestCase):
    def test_publish(self):
        with socketPub(host, port) as pub:
            pub.publish("123")
class TestSocketSub(unittest.TestCase):
    def test_subscribe(self):
        CNT = 100 
        def publish(q_pub):
            with socketPub(host, port) as pub:
                for i in range(CNT):
                    pub.publish(str(i))
                    q_pub.put(str(i))
            time.sleep(1)
        def subscribe(q_sub):
            with socketSub([(host, port)]) as sub:
                for string in sub.subscribe(CNT):
                    q_sub.put(string)
        q_pub, q_sub = Queue(), Queue() 
        p_pub = Process(target=publish, args=(q_pub, ))
        p_sub = Process(target=subscribe, args=(q_sub, ))
        p_sub.start()
        p_pub.start()
        p_sub.join()
        for i in range(CNT):
            self.assertEqual(q_pub.get(), q_sub.get())

测试

$python -m unittest test.py
..
----------------------------------------------------------------------
Ran 2 tests in 0.480s

OK

注意

  1. 再publish 的时候, bind和第一次send之间要有延时, 否则会丢帧, 经测试200毫秒是一个合适的值.
  2. 接受端要有socket.setsockopt_string(zmq.SUBSCRIBE, ""), 代表不进行任何的过滤.

你可能感兴趣的:(杂谈,zeroMQ)