一个线程中如果有多个sokect,同时需要收发数据时,zmq提供polling sockets实现,不用在send()或者recv()时阻塞socket。
下面是一个在recv()端接受信息的poller()轮询接受代码。
#!/usr/bin/python
# -*- coding: utf-8
import zmq
import random
import time
from multiprocessing import Process
def server_push(port="5556"):
context = zmq.Context()
socket = context.socket(zmq.PUSH)
socket.bind("tcp://*:%s" % port)
print "Running server on port: ", port
# serves only 5 request and dies
for reqnum in range(10):
if reqnum < 6:
socket.send("Continue")
else:
socket.send("Exit")
break
time.sleep (1)
def server_pub(port="5558"):
context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:%s" % port)
publisher_id = random.randrange(0,9999)
print "Running server on port: ", port
# serves only 5 request and dies
for reqnum in range(10):
# Wait for next request from client
topic = random.randrange(8,10)
messagedata = "server#%s" % publisher_id
print "%s %s" % (topic, messagedata)
socket.send("%d %s" % (topic, messagedata))
time.sleep(1)
def client(port_push, port_sub):
context = zmq.Context()
socket_pull = context.socket(zmq.PULL)
socket_pull.connect ("tcp://localhost:%s" % port_push)
print "Connected to server with port %s" % port_push
socket_sub = context.socket(zmq.SUB)
socket_sub.connect ("tcp://localhost:%s" % port_sub)
socket_sub.setsockopt(zmq.SUBSCRIBE, "9")
#zmq.SUBSCRIBE创建一个消息过滤标志,订阅以9为前缀的消息
print "Connected to publisher with port %s" % port_sub
# 初始化Poller
poller = zmq.Poller()
poller.register(socket_pull, zmq.POLLIN)
poller.register(socket_sub, zmq.POLLIN)
# Work on requests from both server and publisher
#如果设置为POLLIN则刷新recv,与之对应的是POLLOUT刷新send发送事件,也可以同时设置两个标志
should_continue = True
while should_continue:
socks = dict(poller.poll())
if socket_pull in socks and socks[socket_pull] == zmq.POLLIN:
message = socket_pull.recv()
print "Recieved control command: %s" % message
if message == "Exit":
print "Recieved exit command, client will stop recieving messages"
should_continue = False
if socket_sub in socks and socks[socket_sub] == zmq.POLLIN:
string = socket_sub.recv()
topic, messagedata = string.split()
#Python split()通过指定分隔符对字符串进行切片,如果参数num 有指定值,则仅分隔 num 个子字符串
#str.split(str="", num=string.count(str)).
# str -- 分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等,num -- 分割次数
print "Processing ... ", topic, messagedata
if __name__ == "__main__":
# Now we can run a few servers
server_push_port = "5556"
server_pub_port = "5558"
Process(target=server_push, args=(server_push_port,)).start()
Process(target=server_pub, args=(server_pub_port,)).start()
Process(target=client, args=(server_push_port,server_pub_port,)).start()
在poller中POLLIN和POLLOUT的区别是pollin在recv()端,负责刷新recv端口,来接受信息,POLLOUT在send()端口,负责刷新send端,来发送消息。
flag (int, default=POLLIN|POLLOUT) – 0MQpoll flags. If flag|POLLIN, recv events will be flushed. If flag|POLLOUT, sendevents will be flushed. Both flags can be set at once, which is the default.
这是程序运行结果。
-
Running server on port: 5556 Running server on port: 5558 8 server#5230 Connected to server with port 5556 Connected to publisher with port 5558 Recieved control command: Continue 8 server#5230 Recieved control command: Continue 9 server#5230 Processing ... 9 server#5230 Recieved control command: Continue 9 server#5230 Processing ... 9 server#5230 Recieved control command: Continue 9 server#5230 Processing ... 9 server#5230 Recieved control command: Continue 9 server#5230 Processing ... 9 server#5230 Recieved control command: Continue 9 server#5230 Processing ... 9 server#5230 Recieved control command: Exit Recieved exit command, client will stop recieving messages 8 server#5230 9 server#5230 9 server#5230 Process finished with exit code 0