ZMQ是什么?
  这是个类似于Socket的一系列接口,他跟Socket的区别是:普通 的socket是端到端的(1:1的关系),而ZMQ却是可以N:M 的关系,人们对BSD套接字的了解较多的是点对点的连接,点对点连接需要显式地建立连接、销毁连接、选择协议(TCP/UDP)和处理错误等,而ZMQ屏 蔽了这些细节,让你的网络编程更为简单。ZMQ用于node与node间的通信,node可以是主机或者是进程。
  引用官方的说法: “ZMQ(以下ZeroMQ简称ZMQ)是一个简单好用的传输层,像框架一样的一个socket library,他使得Socket编程更加简单、简洁和性能更高。是一个消息处理队列库,可在多个线程、内核和主机盒之间弹性伸缩。ZMQ的明确目标是 “成为标准网络协议栈的一部分,之后进入Linux内核”。现在还未看到它们的成功。但是,它无疑是极具前景的、并且是人们更加需要的“传统”BSD套接 字之上的一 层封装。ZMQ让编写高性能网络应用程序极为简单和有趣。”
  以上拷贝至百度百科。
  对了使用ZMQ之前必须要有那么几样东西libzmq.lib,zhelpers.hpp,zmq.h,zmq.hpp。这些都可以在ZMQ的官网下载。
 
  接下来是来说说ZMQ有模式,可以归纳成三种,请求回应模式(1对N),发布订阅模式(单向1对N),还有推拉模型。
1:请求回应模式(Req-Rep)
        
可以有多个client,这个很容易理解跟TCP很像,但服务器与客户端必须是1问1答的形式。直接看源代码。
#include <zmq.hpp>
#include <string>
#include <iostream>
#include <windows.h>
#include<zhelpers.hpp>
using namespace std; DWORD WINAPI MyThread_client(LPVOID lpParamter)
{
zmq::context_t context ();
//建立套接字
zmq::socket_t socket (context, ZMQ_REQ); std::cout << "Connecting to hello world server..." << std::endl;
//连接服务器
socket.connect ("tcp://localhost:5555"); for (int request_nbr = ; request_nbr != ; request_nbr++) {
s_send (socket, "hello");
std::cout << "Client1 Received :" <<s_recv (socket)<< std::endl; Sleep();
}
return ; } DWORD WINAPI MyThread_client1(LPVOID lpParamter)
{
zmq::context_t context ();
//建立套接字
zmq::socket_t socket (context, ZMQ_REQ); std::cout << "Connecting to hello world server..." << std::endl;
//连接服务器
socket.connect ("tcp://localhost:5555"); for (int request_nbr = ; request_nbr != ; request_nbr++) {
s_send (socket, "SB");
std::cout << "Client2 Received :" <<s_recv (socket)<< std::endl; Sleep();
}
return ; } DWORD WINAPI MyThread_servce(LPVOID lpParamter)
{
zmq::context_t context ();
zmq::socket_t socket (context, ZMQ_REP);
//绑定端口
socket.bind ("tcp://*:5555"); while (true) {
std::cout << "Servce Received: "<<s_recv (socket)<< std::endl;
s_send (socket, "world");
}
} int main ()
{ HANDLE hThread1 = CreateThread(NULL, , MyThread_client, NULL, , NULL);
HANDLE hThread2 = CreateThread(NULL, , MyThread_servce, NULL, , NULL); HANDLE hThread3 = CreateThread(NULL, , MyThread_client1, NULL, , NULL); while();
return ;
}

运行结果:

  这里我建立了两个客户端和一个服务器,每个都独立运行一个线程。客户端1发了“hello”,客户端2发了“SB”,服务器都能接收到并且返回了world。

2:发布订阅模式(PUB-SUB)

所谓发布订阅,比如天气预报,当很多人订阅之后,中心服务器直接往订阅的人发送就可以了,不需要管对方有没有收到。也就是1对N的模式。这里还有重要的一个概念,频道:跟收音机的频道类似,订阅者设定了频道才能听到该频道的消息

  

看例程序:

#include <zmq.hpp>
#include <string>
#include <iostream>
#include <windows.h>
#include<zhelpers.hpp>
using namespace std; //订阅1
DWORD WINAPI MyThread_sub1(LPVOID lpParamter)
{
zmq::context_t context();
zmq::socket_t subscriber (context, ZMQ_SUB);
//连接
subscriber.connect("tcp://localhost:5563");
//设置频道B
subscriber.setsockopt( ZMQ_SUBSCRIBE, "A", );
while () { // Read envelope with address
std::string address = s_recv (subscriber);
// Read message contents
std::string contents = s_recv (subscriber); std::cout << "订阅1:[" << address << "] " << contents << std::endl;
}
return ; }
//订阅2
DWORD WINAPI MyThread_sub2(LPVOID lpParamter)
{
zmq::context_t context();
zmq::socket_t subscriber (context, ZMQ_SUB);
//连接
subscriber.connect("tcp://localhost:5563");
//设置频道B
subscriber.setsockopt( ZMQ_SUBSCRIBE, "B", );
while () { // Read envelope with address
std::string address = s_recv (subscriber);
// Read message contents
std::string contents = s_recv (subscriber); std::cout << "订阅2:[" << address << "] " << contents << std::endl;
}
return ; }
//订阅3
DWORD WINAPI MyThread_sub3(LPVOID lpParamter)
{
zmq::context_t context();
zmq::socket_t subscriber (context, ZMQ_SUB);
//连接
subscriber.connect("tcp://localhost:5563");
//设置频道B
// subscriber.setsockopt( ZMQ_SUBSCRIBE, "B", 1);
while () { // Read envelope with address
std::string address = s_recv (subscriber);
// Read message contents
std::string contents = s_recv (subscriber); std::cout << "订阅3:[" << address << "] " << contents << std::endl;
}
return ; }
//发布线程
DWORD WINAPI MyThread_pub(LPVOID lpParamter)
{
// Prepare our context and publisher
zmq::context_t context();
zmq::socket_t publisher(context, ZMQ_PUB);
publisher.bind("tcp://*:5563"); while () {
// Write two messages, each with an envelope and content
s_sendmore (publisher, "A");
s_send (publisher, "We don't want to see this"); Sleep ();
s_sendmore (publisher, "B");
s_send (publisher, "We would like to see this");
Sleep (); }
} int main ()
{
HANDLE hThread1 = CreateThread(NULL, , MyThread_pub, NULL, , NULL);
Sleep();
HANDLE hThread2 = CreateThread(NULL, , MyThread_sub1, NULL, , NULL);
HANDLE hThread3 = CreateThread(NULL, , MyThread_sub2, NULL, , NULL);
HANDLE hThread4 = CreateThread(NULL, , MyThread_sub3, NULL, , NULL);
while();
return ;
}

结果:

例程中,设置了1个发布端和3个订阅端,订阅端订阅的频道分别是是A,B和没有订阅,发布端发布了对应频道的订阅消息。由此订阅3没有设置频道,所以收不到消息。
 
3:推拉模式,这个词语感觉污,还是我想歪了。还没研究过,不过看网上说的,跟发布订阅模式类似,只是可以负载均衡。目前项目中也没有用到,下次有机会再研究吧。
ZEROMQ官网的github上面有详细的例程:https://github.com/imatix/zguide/tree/master/examples/
 

消息队列之ZeroMQ(C++)的更多相关文章

  1. 消息队列库——ZeroMQ

    消息队列库——ZeroMQ ZeroMQ(简称ZMQ)是一个基于消息队列的多线程网络库,其对套接字类型.连接处理.帧.甚至路由的底层细节进行抽象,提供跨越多种传输协议的套接字. ZMQ是网络通信中新的 ...

  2. 消息队列性能对比——ActiveMQ、RabbitMQ与ZeroMQ(译文)

    Dissecting Message Queues 概述: 我花了一些时间解剖各种库执行分布式消息.在这个分析中,我看了几个不同的方面,包括API特性,易于部署和维护,以及性能质量..消息队列已经被分 ...

  3. zeromq的安装,部署(号称最快的消息队列,消息中间件)

    1:Storm作为一个实时处理的框架,产生的消息需要快速的进行处理,比如存在消息队列ZeroMQ里面. 由于消息队列ZeroMQ是C++写的,而我们的程序是运行在JVM虚拟机里面的.所以需要jzmq这 ...

  4. 消息队列&Celery&RabbitMQ&zeromq

    一.消息队列 什么是消息队列? “消息队列”是在消息的传输过程中保存消息的容器. “消息”是在两台计算机间传送的数据单位.消息可以非常简单,例如只包含文本字符串:也可以更复杂,可能包含嵌入对象. 消息 ...

  5. 关于消息队列的使用----ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ

    一.消息队列概述消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构.目前使用较多的消息队列有ActiveMQ,RabbitM ...

  6. 消息队列ZeroMQ

    消息队列概念 消息队列技术是分布式应用间交换信息的一种技术.消息队列可以驻留在内存或者磁盘上,队列存储消息直到它们被应用程序读走.通过消息队列,应用程序可以独立的执行,它们不需要知道彼此的位置,或者在 ...

  7. RabbitMQ,Apache的ActiveMQ,阿里RocketMQ,Kafka,ZeroMQ,MetaMQ,Redis也可实现消息队列,RabbitMQ的应用场景以及基本原理介绍,RabbitMQ基础知识详解,RabbitMQ布曙

    消息队列及常见消息队列介绍 2017-10-10 09:35操作系统/客户端/人脸识别 一.消息队列(MQ)概述 消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以 ...

  8. Netty构建分布式消息队列(AvatarMQ)设计指南之架构篇

    目前业界流行的分布式消息队列系统(或者可以叫做消息中间件)种类繁多,比如,基于Erlang的RabbitMQ.基于Java的ActiveMQ/Apache Kafka.基于C/C++的ZeroMQ等等 ...

  9. Redis 做消息队列

    一般来说,消息队列有两种场景,一种是发布者订阅者模式,一种是生产者消费者模式.利用redis这两种场景的消息队列都能够实现.定义: 生产者消费者模式:生产者生产消息放到队列里,多个消费者同时监听队列, ...

随机推荐

  1. SQL Server触发器

    一﹕ 触发器是一种特殊的存储过程﹐它不能被显式地调用﹐而是在往表中插入记录﹑更新记录或者删除记录时被自动地激活.所以触发器可以用来实现对表实施复杂的完整性约`束. 二﹕ SQL Server为每个触发 ...

  2. ASP.Net 打通服务器代码和前台界面的特殊符号

    1.<% %>用来绑定后台代码 如: < % ;i<;i++) { Reaponse.Write(i.ToString()); } %> 2.<%# %> 是 ...

  3. linux 正则表达式使用

    1.正则表达式概念 正则表达式使用单个字符串来描述.匹配一系列符合某个句法规则的字符串.在很多文本编辑里,正则表达式通常被用来检索.替换那些符合某个模式的文本. 正则表达式的基本元素包括普通字符和元字 ...

  4. awk命令和grep命令的使用

    1.遇到需求:用ping命令去检测系统网络延迟 跑 ping baidu.com -c 3,想要直接得到平均延迟. ping baidu.com -c 3 | grep rtt | awk -F \/ ...

  5. r-cnn学习(九):学习总结

    首先看下代码文件夹的说明(这部分转自:http://blog.csdn.net/bailufeiyan/article/details/50749694) tools 在tools文件夹中,是我们直接 ...

  6. Qt - 错误总结 - QObject::connect: Cannot queue arguments of type 'PVCI_CAN_OBJ' (Make sure 'PVCI_CAN_OBJ' is registered using qRegisterMetaType().)

    背景:一个线程通过signal-slot发送PVCI_CAN_OBJ类型的值到主线程中, 错误提示: QObject::connect: Cannot queue arguments of type ...

  7. React入门

    一.引入Reactjs 方法一:直接下载相关js文件引入网页,其中react.js 是 React 的核心库,react-dom.js 是提供与 DOM 相关的功能,Browser.js 的作用是将 ...

  8. [不断更新]iOS开发常用技术

    1.修改默认初始化方法 构建便利构造器 修改默认init初始化 .m文件中 @implementation 类名 -(id)init{ self=[super init]; printf(" ...

  9. js将多个方法添加到window对象上的多种方法

    方法一:(最简单也是最笨的方法) window.a = function(){}window.b = function(){}window.c = function(){} 方法二:(利用jq的ext ...

  10. 【React】dva-cli建立脚手架后发现页面样式不对的问题

    用dva-cli作为脚手架建立工程后,开始尝试编写页面.然后立马发现一个坑爹的问题. 在我less文件里面写了一个class ,比如:MainHead. 但是编译出来之后发现css文件里面变成了 Ma ...