目的
用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
注意
- 再publish 的时候, bind和第一次send之间要有延时, 否则会丢帧, 经测试200毫秒是一个合适的值.
- 接受端要有
socket.setsockopt_string(zmq.SUBSCRIBE, "")
, 代表不进行任何的过滤.