C++通讯组件阅读笔记
阅读这方面的知识是因为,项目中各个界面之间需要传递信息,目前使用的还是信号和槽的方式,想要探究一下有没有更高效的、可扩展的方式。
高速并发消息通信框架ZeroMQ
ZeroMQ是什么
通过阅读了几篇博文,对其进行总结如下:
- ZeroMq简称ZMQ。是一个可以在线程间、进程间、不同的协议之间、广播进行消息传递的并发式框架。
- ZMQ在网络上属于新的一层,在传输层和应用层之间。可伸缩、可并行。
- ZMQ封装了socket,可以完成异步消息处理任务。
- ZMQ支持多种语言。它是一种嵌入式的框架,封装了网络通信、消息队列、线程调度等功能。应用程序通过加载ZMQ库文件,通过调用其提供的简洁API来实现高性能的网络通信。
- ZMQ的通信单元是消息,它只关系消息的长度,不关系格式,可以使用任何格式
ZMQ的三种模型
第一种:请求回应模型(Request-Reply),客户端发起请求,服务器端接受请求。一个服务器可以连接多个客户端。
第二种:发布订阅模型(Publish-Subscribe),感觉有点像观察者模式。pub对应被观察者,sub对应观察者。(思考是否能使用这种模型用在模块之间的级联删除中。假如A模块下面是B模块,A模块删除时,B模块也要删除,则B就是sub,A就是Pub,A在删除时要向B发出信息,告诉B也要同时删除)
另外一个例子:服务器不断更新不同城市的天气,作为Pub,客户端作为sub,可以订阅自己感兴趣的城市(通过过滤器)的天气信息。服务器不用关心
第三种:管道模型(Push-Pull),这种主要用于多并发任务吧。感觉目前还用不上。先不过多了解。
来浅看一下ZMQ怎么用(API)
ZMQ提供四种通信协议:
1.进程之间的:inproc://
2.线程之间的:ipc://
3.机器间:tcp://
4.广播:pgm://
API均以zmq_开头
context上下文
在使用ZMQ库之前,必须要创建一个 ZMQ context上下文。
上下文是一个容器,包含了该进程下的所有套接字。
当一个进程终止时,context必须要被销毁掉。
socket套接字
创建一个套接字:
void *zmq_socket (void *context, int type);
conext为上下文
type的类型:
模式 | type | 说明 |
---|---|---|
请求回应 | ZMQ_REQ | 客户端使用 |
请求回应 | ZMQ_REP | 服务器使用 |
发布订阅 | ZMQ_PUB | publisher使用 |
发布订阅 | ZMQ_SUB | subscriber使用 |
设置socket
int zmq_getsockopt (void *socket, int option_name, void *option_value, size_t *option_len);
//用来设置订阅的内容
int zmq_setsockopt (void *socket, int option_name, const void *option_value, size_t option_len);
在使用第二种发布订阅模式时,必须使用setsocket来设置订阅的内容。optionname为ZMQ_SUBSCRIBE,option_value为过滤器,用来过滤服务器发来的消息。
如果不设置订阅内容,就收不到任何消息。
订阅信息可以是任何字符串,可以设置多次。
订阅者可以选择不接受某类消息,也是通过setsocket实现的。
另外一些注意事项:
PUB-SUB套接字组合是异步的。客户端在一个循环体中使用zmq_recv()接收消息,如果向SUB套接字发送消息则会报错;类似地,服务端可以不断地使用zmq_send()发送消息,但不能在PUB套接字上使用zmq_recv()。
你无法得知SUB是何时开始接收消息的。就算你先打开了SUB套接字,后打开PUB发送消息,这时SUB还是会丢失一些消息的,因为建立连接是需要一些时间的。很少,但并不是零。
ZMQ版本号
int a, b, c = 0;
zmq_version(&a, &b, &c);
std::cout << "zmq-version:" << a << "-" << b << "-" << c << std::endl;
高性能通信库 NanoMsg
这个大概看了看,有空再总结吧
参考文章
1.https://gitee.com/solym/ZeroMQ-Guide-Zh/blob/master/chapter1.md.
2. https://www.cnblogs.com/chenny7/p/6245236.html.