zmq订阅发布模式

server端代码:

#coding=utf-8
'''''
服务端,发布模式
'''
import zmq
from random import randrange context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://127.0.0.1:8000") while True:
zipcode = randrange(1, 100000)
temperature = randrange(-80, 135)
relhumidity = randrange(10, 60) socket.send("%i %i %i" % (zipcode,temperature , relhumidity))

客户端代码:

#coding=utf-8
'''''
订阅模式,如果设置了过滤条件,那么只会接收到以过滤条件开头的消息
'''
import sys
import zmq # Socket to talk to server
context = zmq.Context()
socket = context.socket(zmq.SUB) print("Collecting updates from weather server...")
socket.connect("tcp://127.0.0.1:8000") # Subscribe to zipcode, default is NYC, 10001
zip_filter = sys.argv[1] if len(sys.argv) > 1 else "10002" #此处设置过滤条件,只有以 zip_filter 开头的消息才会被接收
socket.setsockopt(zmq.SUBSCRIBE, zip_filter) # Process 5 updates
total_temp = 0
for update_nbr in range(5):
string = socket.recv()
print string
zipcode, temperature, relhumidity = string.split()
total_temp += int(temperature) print("Average temperature for zipcode '%s' was %dF" % (
zip_filter, total_temp / update_nbr)
)

总结  

1、 zmq的程序,也是要分清服务端和客户端的,服务端也是要绑定ip和端口的

2、 如果我们先启动客户端,后启动服务端,那么程序是可以正常运行的,换成socket,就不行,socket只能先启动服务端,后启动客户端

3、 学习zmq的过程,千万别总想着socket,你能用socket传输文件,但是如果用zmq做同样的事情,那你就错误的使用了zmq,记住,这是一个消息通信库,它自己实现了一些协议,使得我们可以非常轻松的在节点间,进程间,线程间传递消息,如果你对我刚才说的节点间,进程间,线程间传递消息没什么兴趣,说明,你平日里写的程序都是单进程,单线程的,只管顺序执行就好了,其他的不用考虑。

4、广播,这种模式没有队列缓存,断开之后数据将丢失

下面,分析这两段程序。

1、 不论是服务端还是客户端,都需要获得zmq上下文

context = zmq.Context()

2、获得socket,这个socket不是我们平日里以为的那个socket。zmq里叫socket,我猜可能是为了方便大家学习才这么命名。它的表现,已经远远的超出了我们对以前的那个socket的了解。每一个socket都是有自己的类型的,示例中,服务端的socket的类型是zmq.PUB,客户端的socket的类型是zmq.SUB,pub是发布,sub是订阅。说的通俗点,就是有一个pub节点,可以有多个sub节点,pub节点发出去的消息,如果sub节点没有设置过滤条件,那么就会接收所有的消息,如果有过滤条件,就只接收满足过滤条件的消息。想想看,有没有那么一个时刻,你希望你的程序等待一个命令,收到命令后,你让程序去做一些事情?那么pub与sub模式非常适合这种应用场景。

3、设置过滤条件很简单 

socket.setsockopt(zmq.SUBSCRIBE, zip_filter)

第二个参数就是你期望的过滤条件,只有那些以这个过滤条件开头的消息才会被接收  

问答环节

问题1: 如果想创建多个socket怎么写?

答: 一个上下文可以创建任意多个socket,完全不受限制

问题2: 明明先启动了客户端,后启动的服务端,为啥有些消息却没有收到呢?

答: 就算你先启动了客户端,服务端pub出去的一些消息也还是可能没有被收到,因为你启动服务端时,服务端与客户端要建立连接,而这个时候,消息其实已经发出去了,所以你没收到。

问题3: 在订阅发布模型中,如果客户端断开连接,或是服务端断开连接会产生什么样的影响

答: 如果是客户端断开连接,没什么的,就好比一堆人在听收音机,现在离开一个人,收音机继续播放喽。如果是服务端断开了呢,比如程序死掉了,那么请放心,客户端不会发生崩溃,只是阻塞在socket.recv() 这条语句上,更神奇的是,如果你恢复了服务端

现在,我们修改一下客户端程序

#coding=utf-8
'''''
订阅模式,如果设置了过滤条件,那么只会接收到以过滤条件开头的消息
'''
import sys
import zmq
import time # Socket to talk to server
context = zmq.Context()
socket = context.socket(zmq.SUB) print("Collecting updates from weather server...")
socket.connect("tcp://localhost:8000") # Subscribe to zipcode, default is NYC, 10001
zip_filter = sys.argv[1] if len(sys.argv) > 1 else "10002" #此处设置过滤条件,只有以 zip_filter 开头的消息才会被接收
socket.setsockopt(zmq.SUBSCRIBE, zip_filter) # Process 5 updates
total_temp = 0
for update_nbr in range(50):
print 'wait recv'
string = socket.recv()
print 'has recv'
time.sleep(1)
print string
zipcode, temperature, relhumidity = string.split()
total_temp += int(temperature) print("Average temperature for zipcode '%s' was %dF" % (
zip_filter, total_temp / update_nbr)
)

服务端

#coding=utf-8
'''''
服务端,发布模式
'''
import zmq
import time
from random import randrange context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:8000") while True:
zipcode = randrange(1, 100000)
temperature = randrange(-80, 135)
relhumidity = randrange(10, 60) socket.send("%i %i %i" % (10002,temperature , relhumidity))

  服务端和客户端都启动,这时候,客户端收到一条消息后会睡一秒钟,但是服务端却是一刻不停的在发送消息,那么问题来了,一个发的快,一个收的慢,那么这时候把服务端停掉会怎样呢?

  实际的效果是,服务端停下来了,客户端依然在接收消息,因为有一些消息被缓存起来了,虽然服务端不再发送了,客户端却依然可以接收得到,但这种接收,只是从之前接收的缓冲区里取数据。

  现在,我们在服务端最后加上一条语句,time.sleep(2),这样,服务端发送一条消息后,睡两秒钟,发的慢,收的快了,我们再次启动服务端和客户端,当客户端收到一些消息后,关掉服务端,这次,客户端很快就停止接收了,因为发的慢,所以缓冲区里没有数据,现在,我们再次启动服务端,你会发现,客户端又开始接收数据了,哈哈,神奇吧!

  

saltstack系列(三)——zmq订阅/发布模式的更多相关文章

  1. saltstack系列(四)——zmq Paraller Pipeline模式

    push/pull模式 push/pull模式,这是一个什么模式呢?战争时期,食物紧缺,实行配给制,大家都排好队,有人专门发放食物,前一个人领取了食物,后一个人跟上继续领取食物,这个push端就是发放 ...

  2. 设计模式---订阅发布模式(Subscribe/Publish)

    设计模式---订阅发布模式(Subscribe/Publish) 订阅发布模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象.这个主题对象在自身状态变化时,会通知所有订阅者对象,使 ...

  3. RabbitMQ下的生产消费者模式与订阅发布模式

    所谓模式,就是在某种场景下,一类问题及其解决方案的总结归纳.生产消费者模式与订阅发布模式是使用消息中间件时常用的两种模式,用于功能解耦和分布式系统间的消息通信,以下面两种场景为例: 数据接入   假设 ...

  4. Kafka下的生产消费者模式与订阅发布模式

    原文:https://blog.csdn.net/zwgdft/article/details/54633105   在RabbitMQ下的生产消费者模式与订阅发布模式一文中,笔者以“数据接入”和“事 ...

  5. js设计模式之代理模式以及订阅发布模式

    为啥将两种模式放在一起呢?因为这样文章比较长啊. 写博客的目的我觉得首要目的是整理自己的知识点,进而优化个人所得知识体系.知识成为个人的知识,就在于能够用自己的话表达同一种意义. 本文是设计模式系列文 ...

  6. ionic2踩坑之订阅发布模式的实现

    原文地址:http://www.cnblogs.com/eccainiao/p/6429536.html 转载请说明. 在ionic2中实现订阅发布模式,需要用到Events. Events下面有三个 ...

  7. Publisher/Subscriber 订阅-发布模式

    Publisher/Subscriber 订阅-发布模式 本博后续将陆续整理这些年做的一些预研demo,及一些前沿技术的研究,与大家共研技术,共同进步. 关于发布订阅有很多种实现方式,下面主要介绍WC ...

  8. AngularJS的简单订阅发布模式例子

    控制器之间的交互方式广播 broadcast, 发射 emit 事件 类似于 js中的事件 , 可以自己定义事件 向上传递直到 document 在AngularJs中 向上传递直到 rootScop ...

  9. 订阅发布模式eventEmiter

    // 订阅发布模式 class EventEmitter { constructor() { this._events = {}; } on(name, callback) { if (this._e ...

随机推荐

  1. main(argc,argv[])

    每个C语言程序都必须有一个称为main()的函数,作为程序启动的起点.当执行程序时,命令行参数(command-line argument)(由shell逐一解析)通过两个入参提供给main()函数. ...

  2. 关于iframe和div窗口中ajax请求200状态时执行的回调问题

    上一篇说了在ajax回调里面处理iframe窗口的刷新问题,这一篇记录一下遇到的一个分别在iframe和div窗口中ajax请求200状态时执行的回调问题. 我们先来看一下ajax请求的写法(这里使用 ...

  3. 查看 nginx 的并发连接数

    通过查看Nginx的并发连接,我们可以更清除的知道网站的负载情况.Nginx并发查看有两种方法(之所以这么说,是因为笔者只知道两种),一种是通过web界面,一种是通过命令,web查看要比命令查看显示的 ...

  4. FreeMarker配置详解

    首先需要添加freemarker.jar到项目,如果项目中有spring或者spirngmvc,需要整合,首先配置freemarkerConfig,代码结构如下:         <!-- 设置 ...

  5. Fast Arrangement (线段树,延迟标志)

    个人心得:线段树的延迟标志确实是减少了很多时间,思想比较简单,但是实现得时候和建立延迟的时候比较麻烦. 按照我的一些理解,就是更新时找到完全覆盖的区间时,更新延迟标志,不再往下更新,但此时父节点啥的都 ...

  6. python 的日志logging模块

    1.简单的将日志打印到屏幕 import logging logging.debug('This is debug message')logging.info('This is info messag ...

  7. bzoj 2878 [Noi2012]迷失游乐园——树上的期望dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2878 很好的树上概率题的思路,就是分成up和down. 代码中有众多小细节.让我弃疗好几天的 ...

  8. Oracle配置文件tnsnames.ora新增链接后连接报错:ORA-12154: TNS:无法解析指定的标识符

    一个空格引发的血案:在tnsnames. ora文件中新加了一个配置,该配置估计当时是拷的别人的直接粘贴上去的,然后发现用pl/sql连接就一直报错了,后面排除了用户名和密码问题和后,仔细看了该文件才 ...

  9. git 查看、创建、切换、删除、重命名和推送分支

    1.查看本地所有分支:前面有 “*” 的是当前所处的分支 $ git branch test-A * test-B 2.查看本地和远程服务器的所有分支: $ git branch -a test-A ...

  10. easyui的datagird动态设置当前页数

    if (ishas) { $("#tg").datagrid("options").pageNumber = 1; $('#tg').datagrid('rel ...