参考网址:http://zhou-xingbo.iteye.com/blog/951859
常用的通讯模式有三类(两个解释都挺好,先保存下来):
1. 请求应答模式(Request-Reply)
消息双向的,有来有往,req端请求的消息,rep端必须答复给req端
2. 订阅发布模式 (sub 和 pub)
消息单向的,有去无回的。可按照发布端可发布制定主题的消息,订阅端可订阅喜欢的主题,订阅端只会收到自己已经订阅的主题。发布端发布一条消息,可被多个订阅端同事收到。
3. push pull模式
消息单向的,也是有去无回的。push的任何一个消息,始终只会有一个pull端收到消息.
后续的代理模式和路由模式等都是在三种基本模式上面的扩展或变异。
1.请求回应模型。由请求端发起请求,并等待回应端回应请求。从请求端来看,一定是一对对收发配对的;
反之,在回应端一定是发收对。请求端和回应端都可以是1:N的模型。通常把1认为是server,N认为是Client。
0MQ可以很好的支持路由功能(实现路由功能的组件叫做Device),把1:N扩展为N:M(只需要加入若干路由节点)。
从这个模型看,更底层的端点地址是对上层隐藏的。每个请求都隐含回应地址,而应用则不关心它。
2.发布订阅模型。这个模型里,发布端是单向只发送数据的,且不关心是否把全部的信息都发送给订阅者。
如果发布端开始发布信息的时候,订阅端尚未连接上,这些信息直接丢弃。
不过一旦订阅端连接上来,中间会保证没有信息丢失。
同样,订阅端则只负责接收,而不能反馈。
如果发布端和订阅端需要交互(比如要确认订阅者是否已经连接上),则使用额外的socket采用请求回应模型满足这个需求。
3.管道模型。这个模型里,管道是单向的,从PUSH端单向的向PULL端单向的推送数据流。
我使用的是请求回应模型,server为REP模式,等待消息,client为REQ模式,向server请求消息。
一个最简单的例子:
server.py
import zmq context = zmq.Context() socket = context.socket(zmq.REP) socket.bind("tcp://*:5555") message = socket.recv() print "message from client:", message # Send reply back to client socket.send("World")
client.py
import zmq context = zmq.Context() print "Connecting to server..." socket = context.socket(zmq.REQ) socket.connect ("tcp://localhost:5555") socket.send ("Hello") message = socket.recv() print "Received reply: ", message
运行结果:
$ python server.py
message from client: Hello
$ python client.py
Connecting to server...
Received reply: World
一个解决了我很多疑问的网址:
http://www.searchtb.com/2012/08/zeromq-primer.html
其中说明了:
a) 服务端和客户端无论谁先启动,效果是相同的,这点不同于Socket。
b) 在服务端收到信息以前,程序是阻塞的,会一直等待客户端连接上来。
c) 服务端收到信息以后,会send一个“World”给客户端。值得注意的是一定是client连接上来以后,send消息给Server,然后 Server再rev然后响应client,这种一问一答式的。如果Server先send,client先rev是会报错的。
d) ZMQ通信通信单元是消息,他除了知道Bytes的大小,他并不关心的消息格式。因此,你可以使用任何你觉得好用的数据格式。Xml、Protocol Buffers、Thrift、json等等。