ZeroMQ学习笔记
简介
ZeroMQ是一个高性能的分布式网络库,它的特性包括:
- 看起来像是嵌入式网络库,行为更像是分布式并发库
- 对于集群产品、超级计算领域来说,比TCP更快
- 支持以进程内、IPC、TCP、组播方式携带载荷
- 支持fanout, pubsub, pipeline, request-reply等N-to-N通信模式
Apache Storm 0.9之前的版本默认使用ZeroMQ作为节点通信库。
起步
安装
libzmq
基于C++实现的ZeroMQ核心引擎。安装步骤参考:
1 2 3 4 5 6 |
mkdir libzmq && pushd libzmq git clone https://github.com/zeromq/libzmq src pushd src mkdir build && pushd build cmake -DCMAKE_INSTALL_PREFIX:STRING=/home/alex/CPP/lib/libzmq -DCMAKE_BUILD_TYPE:STRING=Debug .. make && make install |
请求/应答
EchoServer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#include "zmq.h" #include <stdbool.h> #include <string.h> int main() { // 创建一个线程安全的上下为,返回一个非透明句柄(Opaque Handle) void *context = zmq_ctx_new(); // 在指定的上下文中创建zmq套接字,返回一个非透明句柄(Opaque Handle) // 第二个参数为套接字类型,和传统套接字不同,zmq套接字是一种异步消息队列的抽象,队列的语义由套接字类型确定 // ZMQ_REP用于请求-应答模式的服务器端,用于接受请求并给予应答。此类型仅仅支持成对的zmq_recv/zmq_send调用 void *responder = zmq_socket( context, ZMQ_REP ); // REP是REPLY的意思 // 绑定,监听客户端连接 int rc = zmq_bind( responder, "tcp://*:5555" ); if ( rc != 0 ) return -1; while ( true ) { char buf[32]; memset( buf, 0, sizeof( buf )); /** * int zmq_recv (void *socket, void *buf, size_t len, int flags) * 从套接字socket中接收消息,存放到buf中,参数: * len 超过此长度的消息被截断 * flags 不阻塞,如果没有可用消息则调用失败,设置errno为EAGAIN(资源暂时不可用) * 返回值:返回实际接收的消息长度,如果接收失败返回-1 */ int len = zmq_recv( responder, buf, 32, ZMQ_DONTWAIT ); if ( len > -1 ) { printf( "Received message: %s\n", buf ); zmq_send( responder, buf, len, 0 ); } } } |
EchoClient
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#include "zmq.h" int main() { void *context = zmq_ctx_new(); // 套接字类型ZMQ_REQ和ZMQ_REP配合使用 void *requester = zmq_socket( context, ZMQ_REQ ); // 连接到服务器 zmq_connect( requester, "tcp://localhost:5555" ); int req_count; for ( req_count = 0; req_count != 10; req_count++ ) { char buf[32]; int len = sprintf( buf, "Hello %d", req_count ); // 发送消息 zmq_send( requester, buf, len, 0 ); // 接收消息,此时服务器可以尚未启动,客户端会阻塞在此 zmq_recv( requester, buf, 32, 0 ); } // 关闭套接字 zmq_close( requester ); // 销毁上下文 zmq_ctx_destroy( context ); return 0; } |
收发行为
测试上述程序时,你可以先启动客户端。由于服务器没有启动,客户端的zmq_recv调用会阻塞,这种行为和常见的网络库不同。
收发消息时是否阻塞,可以通过zmq_send/zmq_recv的第三个参数flags设置。
字符串
ZeroMQ不理解你发送的消息的格式,它仅仅知道消息的字节长度。ZeroMQ发送字符串时,必须指定恰当的长度,此长度不应包括结尾的\0字符。
Leave a Reply