【配置VS2022和Ubuntu22.04下的ZeroMQ C++安装环境&两设备双向通讯测试案例】
前言

ZeroMQ是个类似于 Socket 的一系列接口,他跟 Socket 的区别是:普通的 socket 是端到端的(1:1的关系),而 ZMQ 却是可以N:M 的关系,人们对 BSD 套接字的了解较多的是点对点的连接,点对点连接需要显式地建立连接、销毁连接、选择协议(TCP/UDP)和处理错误等,而 ZMQ 屏蔽了这些细节,让你的网络编程更为简单。ZMQ 用于 node 与 node 间的通信,node 可以是主机或者是进程。
源码地址:https://download.csdn.net/download/VOR234/92218737
ZMQ有三种通信模式:分别为请求应答模式、发布订阅模式以及推拉模式,本项目拟采用发布订阅模式,主要是考虑到本项目中的协同建图的这种多对一的模式,适用于单项数据的传递。在同两台设备上运行的不同进程之间(或线程间)进行数据交互时,传统的TCP、UDP断开连接后不能自动重连,但开发与维护成本较高。
ZeroMQ(ZMQ) 提供了一种轻量、快速、跨语言的通信机制,支持:
- 发布-订阅(PUB/SUB)
- 请求-应答(REQ/REP)
- 推送-拉取(PUSH/PULL)
- 配对(PAIR)
本文将展示在同一台设备上、不同进程间的三种 ZMQ 通信模型实现:
- 🔁 发布订阅模式(Pub/Sub)
- 🧩 双向发布订阅(两个节点互发)
- 🔗 配对模式(PAIR 双向通信)
相关学习:
【配置VS2022和Ubuntu22.04下的ZeroMQ C++安装环境&两设备双向通讯测试案例】
【同一设备进程间 ZeroMQ 两节点双向通讯测试案例】
1.VS2022下的ZeroMQ C++安装环境
1. 1安装 ZeroMQ
- 下载 ZeroMQ 预编译库:
- 从 https://github.com/zeromq/libzmq/releases 下载 Windows 版本libzmq-v142-x64-4_3_4.zip

- 解压到项目目录,主要是两个DLL和一个LIB有用

1.2 VS2022 项目配置步骤
然后新建C++项目Zero_server,将上面解压的zmq.h添加为头文件

接下来的三个demo我会一一分解,现在需要
-
项目属性配置:
- 链接器 → 输入 → 附加依赖项:添加
libzmq-mt-4_3_4.lib
- 链接器 → 输入 → 附加依赖项:添加
-
将 DLL 文件复制到输出目录:
- 将
libzmq-mt-4_3_4.dll和libsodium.dll复制到Debug和Release目录
- 将
这个版本使用 C 风格的 ZeroMQ API,避免了 C++ 头文件的问题,应该可以正常编译运行。
2.Ubuntu22.04下的ZeroMQ C++安装环境
参考教程见:https://github.com/zeromq/cppzmq
2.1下载源码
如果ubuntu系统github网络环境不好,推荐下面这种方法,在win环境下下载这两个文件,然后scp复制到目标主机
git clone https://github.com/zeromq/cppzmq.git
git clone https://github.com/zeromq/libzmq.git
scp -r D:\中国一重\项目文档\libzmq Tronlong@192.168.170.76:/home/Tronlong/mmcblk0p8/project_code/project
scp -r D:\中国一重\项目文档\cppzmq Tronlong@192.168.170.76:/home/Tronlong/mmcblk0p8/project_code/project


2.2安装libzmq库
Build steps:
- Build libzmq via cmake. This does an out of source build and installs the build files
git clone https://github.com/zeromq/libzmq.gitcd libzmqmkdir buildcd buildcmake ..sudo make -j4 install
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project$ cd libzmq/
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/libzmq$ mkdir build
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/libzmq$ cd build
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/libzmq/build$ cmake ..
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Detected ZMQ Version - 4.3.6
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.2")
-- Performing Test COMPILER_SUPPORTS_CXX11
-- Performing Test COMPILER_SUPPORTS_CXX11 - Success
-- Performing Test COMPILER_SUPPORTS_C11
-- Performing Test COMPILER_SUPPORTS_C11 - Success
-- Performing Test CXX_HAS_TAUT_WARNING
-- Performing Test CXX_HAS_TAUT_WARNING - Success
-- Performing Test CC_HAS_TAUT_WARNING
-- Performing Test CC_HAS_TAUT_WARNING - Success
-- Building draft classes and methods
-- Using radix tree implementation to manage subscriptions
-- Enable WebSocket transport
-- Could NOT find GnuTLS (missing: GNUTLS_LIBRARY GNUTLS_INCLUDE_DIR) (Required is at least version "3.6.7")
CMake Warning at CMakeLists.txt:215 (message):
No WSS support, you may want to install GnuTLS and run cmake again
-- Using builtin sha1
-- Checking for module 'libbsd'
-- Found libbsd, version 0.11.5
-- Using libbsd
-- Looking for strlcpy
-- Looking for strlcpy - not found
-- CURVE security is disabled
-- Looking for kqueue
-- Looking for kqueue - not found
-- Looking for epoll_create
-- Looking for epoll_create - found
-- Looking for epoll_create1
-- Looking for epoll_create1 - found
-- Using polling method in I/O threads: epoll
-- Using polling method in zmq_poll(er)_* API: poll
-- Looking for pselect
-- Looking for pselect - found
-- Using 64 bytes alignment for lock-free data structures
-- Looking for posix_memalign
-- Looking for posix_memalign - found
-- Looking for include file windows.h
-- Looking for include file windows.h - not found
-- Looking for include file condition_variable
-- Looking for include file condition_variable - found
-- Using condition_variable_t implementation: stl11
-- Looking for include file ifaddrs.h
-- Looking for include file ifaddrs.h - found
-- Looking for include file sys/uio.h
-- Looking for include file sys/uio.h - found
-- Looking for include file sys/eventfd.h
-- Looking for include file sys/eventfd.h - found
-- Checking whether EFD_CLOEXEC is supported
-- Performing Test ZMQ_HAVE_EVENTFD_CLOEXEC
-- Performing Test ZMQ_HAVE_EVENTFD_CLOEXEC - Success
-- Looking for if_nametoindex
-- Looking for if_nametoindex - found
-- Looking for SO_PEERCRED
-- Looking for SO_PEERCRED - found
-- Looking for LOCAL_PEERCRED
-- Looking for LOCAL_PEERCRED - not found
-- Looking for SO_BUSY_POLL
-- Looking for SO_BUSY_POLL - found
-- Looking for clock_gettime
-- Looking for clock_gettime - found
-- Looking for fork
-- Looking for fork - found
-- Looking for gethrtime
-- Looking for gethrtime - not found
-- Looking for mkdtemp
-- Looking for mkdtemp - found
-- Looking for accept4
-- Looking for accept4 - found
-- Looking for strnlen
-- Looking for strnlen - found
-- Performing Test HAVE_FLAG_-Wall
-- Performing Test HAVE_FLAG_-Wall - Failed
-- Performing Test HAVE_FLAG_-Wextra
-- Performing Test HAVE_FLAG_-Wextra - Failed
-- Performing Test HAVE_FLAG_-Wno-long-long
-- Performing Test HAVE_FLAG_-Wno-long-long - Failed
-- Performing Test HAVE_FLAG_-Wno-uninitialized
-- Performing Test HAVE_FLAG_-Wno-uninitialized - Failed
-- Performing Test HAVE_FLAG_-pedantic
-- Performing Test HAVE_FLAG_-pedantic - Failed
-- Checking whether noexcept is supported
-- Performing Test ZMQ_HAVE_NOEXCEPT
-- Performing Test ZMQ_HAVE_NOEXCEPT - Success
-- Checking pthread_setname signature
-- Performing Test ZMQ_HAVE_PTHREAD_SETNAME_1
-- Performing Test ZMQ_HAVE_PTHREAD_SETNAME_1 - Failed
-- Performing Test ZMQ_HAVE_PTHREAD_SETNAME_2
-- Performing Test ZMQ_HAVE_PTHREAD_SETNAME_2 - Success
-- Performing Test ZMQ_HAVE_PTHREAD_SETNAME_3
-- Performing Test ZMQ_HAVE_PTHREAD_SETNAME_3 - Failed
-- Performing Test ZMQ_HAVE_PTHREAD_SET_NAME
-- Performing Test ZMQ_HAVE_PTHREAD_SET_NAME - Failed
-- Checking pthread_setaffinity signature
-- Performing Test ZMQ_HAVE_PTHREAD_SET_AFFINITY
-- Performing Test ZMQ_HAVE_PTHREAD_SET_AFFINITY - Success
-- Checking whether SOCK_CLOEXEC is supported
-- Performing Test ZMQ_HAVE_SOCK_CLOEXEC
-- Performing Test ZMQ_HAVE_SOCK_CLOEXEC - Success
-- Checking whether O_CLOEXEC is supported
-- Performing Test ZMQ_HAVE_O_CLOEXEC
-- Performing Test ZMQ_HAVE_O_CLOEXEC - Success
-- Checking whether SO_BINDTODEVICE is supported
-- Performing Test ZMQ_HAVE_SO_BINDTODEVICE
-- Performing Test ZMQ_HAVE_SO_BINDTODEVICE - Success
-- Checking whether SO_KEEPALIVE is supported
-- Performing Test ZMQ_HAVE_SO_KEEPALIVE
-- Performing Test ZMQ_HAVE_SO_KEEPALIVE - Success
-- Checking whether SO_PRIORITY is supported
-- Performing Test ZMQ_HAVE_SO_PRIORITY
-- Performing Test ZMQ_HAVE_SO_PRIORITY - Success
-- Checking whether TCP_KEEPCNT is supported
-- Performing Test ZMQ_HAVE_TCP_KEEPCNT
-- Performing Test ZMQ_HAVE_TCP_KEEPCNT - Success
-- Checking whether TCP_KEEPIDLE is supported
-- Performing Test ZMQ_HAVE_TCP_KEEPIDLE
-- Performing Test ZMQ_HAVE_TCP_KEEPIDLE - Success
-- Checking whether TCP_KEEPINTVL is supported
-- Performing Test ZMQ_HAVE_TCP_KEEPINTVL
-- Performing Test ZMQ_HAVE_TCP_KEEPINTVL - Success
-- Checking whether TCP_KEEPALIVE is supported
-- Performing Test ZMQ_HAVE_TCP_KEEPALIVE
-- Performing Test ZMQ_HAVE_TCP_KEEPALIVE - Failed
-- Checking whether TIPC is supported
-- Performing Test ZMQ_HAVE_TIPC
-- Performing Test ZMQ_HAVE_TIPC - Success
-- Checking whether getrandom is supported
-- Performing Test ZMQ_HAVE_GETRANDOM
-- Performing Test ZMQ_HAVE_GETRANDOM - Success
-- Could NOT find AsciiDoctor (missing: ASCIIDOCTOR_EXECUTABLE)
CMake Warning (dev) at tests/CMakeLists.txt:346 (message):
Test 'test_bind_stream_fuzzer' is not known to CTest.
This warning is for project developers. Use -Wno-dev to suppress it.
CMake Warning (dev) at tests/CMakeLists.txt:346 (message):
Test 'test_bind_ws_fuzzer' is not known to CTest.
This warning is for project developers. Use -Wno-dev to suppress it.
CMake Warning (dev) at tests/CMakeLists.txt:346 (message):
Test 'test_connect_stream_fuzzer' is not known to CTest.
This warning is for project developers. Use -Wno-dev to suppress it.
CMake Warning (dev) at tests/CMakeLists.txt:346 (message):
Test 'test_connect_ws_fuzzer' is not known to CTest.
This warning is for project developers. Use -Wno-dev to suppress it.
CMake Warning (dev) at tests/CMakeLists.txt:346 (message):
Test 'test_socket_options_fuzzer' is not known to CTest.
This warning is for project developers. Use -Wno-dev to suppress it.
-- Configuring done (12.5s)
-- Generating done (1.2s)
-- Build files have been written to: /home/Tronlong/mmcblk0p8/project_code/project/libzmq/build
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/libzmq/build$ sudo make -j4 install
[ 0%] Building C object tests/CMakeFiles/unity.dir/__/external/unity/unity.c.o
[ 0%] Building CXX object CMakeFiles/objects.dir/src/ws_address.cpp.o
[ 0%] Building CXX object CMakeFiles/objects.dir/src/ws_connecter.cpp.o
[ 1%] Building CXX object CMakeFiles/objects.dir/src/ws_decoder.cpp.o
[ 2%] Linking C static library ../lib/libunity.a
[ 2%] Built target unity
[ 2%] Building CXX object CMakeFiles/objects.dir/src/ws_encoder.cpp.o
[ 2%] Building CXX object CMakeFiles/objects.dir/src/ws_engine.cpp.o
[ 2%] Building CXX object CMakeFiles/objects.dir/src/ws_listener.cpp.o
[ 3%] Building C object CMakeFiles/objects.dir/external/sha1/sha1.c.o
[ 3%] Building CXX object CMakeFiles/objects.dir/src/precompiled.cpp.o
[ 3%] Building CXX object CMakeFiles/objects.dir/src/address.cpp.o
[ 3%] Building CXX object CMakeFiles/objects.dir/src/channel.cpp.o
[ 4%] Building CXX object CMakeFiles/objects.dir/src/client.cpp.o
[ 4%] Building CXX object CMakeFiles/objects.dir/src/clock.cpp.o
[ 4%] Building CXX object CMakeFiles/objects.dir/src/ctx.cpp.o
[ 4%] Building CXX object CMakeFiles/objects.dir/src/curve_mechanism_base.cpp.o
[ 5%] Building CXX object CMakeFiles/objects.dir/src/curve_client.cpp.o
[ 5%] Building CXX object CMakeFiles/objects.dir/src/curve_server.cpp.o
[ 5%] Building CXX object CMakeFiles/objects.dir/src/dealer.cpp.o
[ 5%] Building CXX object CMakeFiles/objects.dir/src/devpoll.cpp.o
[ 6%] Building CXX object CMakeFiles/objects.dir/src/dgram.cpp.o
[ 6%] Building CXX object CMakeFiles/objects.dir/src/dist.cpp.o
[ 6%] Building CXX object CMakeFiles/objects.dir/src/endpoint.cpp.o
[ 6%] Building CXX object CMakeFiles/objects.dir/src/epoll.cpp.o
[ 7%] Building CXX object CMakeFiles/objects.dir/src/err.cpp.o
[ 7%] Building CXX object CMakeFiles/objects.dir/src/fq.cpp.o
[ 7%] Building CXX object CMakeFiles/objects.dir/src/io_object.cpp.o
[ 7%] Building CXX object CMakeFiles/objects.dir/src/io_thread.cpp.o
[ 8%] Building CXX object CMakeFiles/objects.dir/src/ip.cpp.o
[ 8%] Building CXX object CMakeFiles/objects.dir/src/ipc_address.cpp.o
[ 8%] Building CXX object CMakeFiles/objects.dir/src/ipc_connecter.cpp.o
[ 8%] Building CXX object CMakeFiles/objects.dir/src/ipc_listener.cpp.o
[ 9%] Building CXX object CMakeFiles/objects.dir/src/kqueue.cpp.o
[ 9%] Building CXX object CMakeFiles/objects.dir/src/lb.cpp.o
[ 9%] Building CXX object CMakeFiles/objects.dir/src/mailbox.cpp.o
[ 9%] Building CXX object CMakeFiles/objects.dir/src/mailbox_safe.cpp.o
[ 10%] Building CXX object CMakeFiles/objects.dir/src/mechanism.cpp.o
[ 10%] Building CXX object CMakeFiles/objects.dir/src/mechanism_base.cpp.o
[ 10%] Building CXX object CMakeFiles/objects.dir/src/metadata.cpp.o
[ 10%] Building CXX object CMakeFiles/objects.dir/src/msg.cpp.o
[ 11%] Building CXX object CMakeFiles/objects.dir/src/mtrie.cpp.o
[ 11%] Building CXX object CMakeFiles/objects.dir/src/norm_engine.cpp.o
[ 11%] Building CXX object CMakeFiles/objects.dir/src/object.cpp.o
[ 11%] Building CXX object CMakeFiles/objects.dir/src/options.cpp.o
[ 12%] Building CXX object CMakeFiles/objects.dir/src/own.cpp.o
[ 12%] Building CXX object CMakeFiles/objects.dir/src/null_mechanism.cpp.o
[ 12%] Building CXX object CMakeFiles/objects.dir/src/pair.cpp.o
[ 12%] Building CXX object CMakeFiles/objects.dir/src/peer.cpp.o
[ 12%] Building CXX object CMakeFiles/objects.dir/src/pgm_receiver.cpp.o
[ 13%] Building CXX object CMakeFiles/objects.dir/src/pgm_sender.cpp.o
[ 13%] Building CXX object CMakeFiles/objects.dir/src/pgm_socket.cpp.o
[ 13%] Building CXX object CMakeFiles/objects.dir/src/pipe.cpp.o
[ 13%] Building CXX object CMakeFiles/objects.dir/src/plain_client.cpp.o
[ 14%] Building CXX object CMakeFiles/objects.dir/src/plain_server.cpp.o
[ 14%] Building CXX object CMakeFiles/objects.dir/src/poll.cpp.o
[ 14%] Building CXX object CMakeFiles/objects.dir/src/poller_base.cpp.o
[ 14%] Building CXX object CMakeFiles/objects.dir/src/polling_util.cpp.o
[ 15%] Building CXX object CMakeFiles/objects.dir/src/pollset.cpp.o
[ 15%] Building CXX object CMakeFiles/objects.dir/src/proxy.cpp.o
[ 15%] Building CXX object CMakeFiles/objects.dir/src/pub.cpp.o
[ 15%] Building CXX object CMakeFiles/objects.dir/src/pull.cpp.o
[ 16%] Building CXX object CMakeFiles/objects.dir/src/push.cpp.o
[ 16%] Building CXX object CMakeFiles/objects.dir/src/random.cpp.o
[ 16%] Building CXX object CMakeFiles/objects.dir/src/raw_encoder.cpp.o
[ 16%] Building CXX object CMakeFiles/objects.dir/src/raw_decoder.cpp.o
[ 17%] Building CXX object CMakeFiles/objects.dir/src/raw_engine.cpp.o
[ 17%] Building CXX object CMakeFiles/objects.dir/src/reaper.cpp.o
[ 17%] Building CXX object CMakeFiles/objects.dir/src/rep.cpp.o
[ 17%] Building CXX object CMakeFiles/objects.dir/src/req.cpp.o
[ 18%] Building CXX object CMakeFiles/objects.dir/src/router.cpp.o
[ 18%] Building CXX object CMakeFiles/objects.dir/src/select.cpp.o
[ 18%] Building CXX object CMakeFiles/objects.dir/src/server.cpp.o
[ 18%] Building CXX object CMakeFiles/objects.dir/src/session_base.cpp.o
[ 19%] Building CXX object CMakeFiles/objects.dir/src/signaler.cpp.o
[ 19%] Building CXX object CMakeFiles/objects.dir/src/socket_base.cpp.o
[ 19%] Building CXX object CMakeFiles/objects.dir/src/socks.cpp.o
[ 19%] Building CXX object CMakeFiles/objects.dir/src/socks_connecter.cpp.o
[ 20%] Building CXX object CMakeFiles/objects.dir/src/stream.cpp.o
[ 20%] Building CXX object CMakeFiles/objects.dir/src/stream_engine_base.cpp.o
[ 20%] Building CXX object CMakeFiles/objects.dir/src/sub.cpp.o
[ 20%] Building CXX object CMakeFiles/objects.dir/src/tcp.cpp.o
[ 21%] Building CXX object CMakeFiles/objects.dir/src/tcp_address.cpp.o
[ 21%] Building CXX object CMakeFiles/objects.dir/src/tcp_connecter.cpp.o
[ 21%] Building CXX object CMakeFiles/objects.dir/src/tcp_listener.cpp.o
[ 21%] Building CXX object CMakeFiles/objects.dir/src/thread.cpp.o
[ 22%] Building CXX object CMakeFiles/objects.dir/src/trie.cpp.o
[ 22%] Building CXX object CMakeFiles/objects.dir/src/radix_tree.cpp.o
[ 22%] Building CXX object CMakeFiles/objects.dir/src/v1_decoder.cpp.o
[ 22%] Building CXX object CMakeFiles/objects.dir/src/v1_encoder.cpp.o
[ 23%] Building CXX object CMakeFiles/objects.dir/src/v2_decoder.cpp.o
[ 23%] Building CXX object CMakeFiles/objects.dir/src/v2_encoder.cpp.o
[ 23%] Building CXX object CMakeFiles/objects.dir/src/v3_1_encoder.cpp.o
[ 23%] Building CXX object CMakeFiles/objects.dir/src/xpub.cpp.o
[ 24%] Building CXX object CMakeFiles/objects.dir/src/xsub.cpp.o
[ 24%] Building CXX object CMakeFiles/objects.dir/src/zmq.cpp.o
[ 24%] Building CXX object CMakeFiles/objects.dir/src/zmq_utils.cpp.o
[ 24%] Building CXX object CMakeFiles/objects.dir/src/decoder_allocators.cpp.o
[ 25%] Building CXX object CMakeFiles/objects.dir/src/socket_poller.cpp.o
[ 25%] Building CXX object CMakeFiles/objects.dir/src/timers.cpp.o
[ 25%] Building CXX object CMakeFiles/objects.dir/src/radio.cpp.o
[ 25%] Building CXX object CMakeFiles/objects.dir/src/dish.cpp.o
[ 26%] Building CXX object CMakeFiles/objects.dir/src/udp_engine.cpp.o
[ 26%] Building CXX object CMakeFiles/objects.dir/src/udp_address.cpp.o
[ 26%] Building CXX object CMakeFiles/objects.dir/src/scatter.cpp.o
[ 26%] Building CXX object CMakeFiles/objects.dir/src/gather.cpp.o
[ 26%] Building CXX object CMakeFiles/objects.dir/src/ip_resolver.cpp.o
[ 27%] Building CXX object CMakeFiles/objects.dir/src/zap_client.cpp.o
[ 27%] Building CXX object CMakeFiles/objects.dir/src/zmtp_engine.cpp.o
[ 27%] Building CXX object CMakeFiles/objects.dir/src/stream_connecter_base.cpp.o
[ 27%] Building CXX object CMakeFiles/objects.dir/src/stream_listener_base.cpp.o
[ 28%] Building CXX object CMakeFiles/objects.dir/src/tipc_address.cpp.o
[ 28%] Building CXX object CMakeFiles/objects.dir/src/tipc_connecter.cpp.o
[ 28%] Building CXX object CMakeFiles/objects.dir/src/tipc_listener.cpp.o
[ 28%] Built target objects
[ 29%] Linking CXX shared library lib/libzmq.so
[ 29%] Linking CXX static library lib/libzmq.a
[ 29%] Built target libzmq-static
[ 30%] Building CXX object tests/CMakeFiles/testutil-static.dir/testutil.cpp.o
[ 30%] Building CXX object CMakeFiles/benchmark_radix_tree.dir/perf/benchmark_radix_tree.cpp.o
[ 30%] Building CXX object tests/CMakeFiles/testutil-static.dir/testutil_monitoring.cpp.o
[ 30%] Built target libzmq
[ 30%] Building CXX object tests/CMakeFiles/testutil-static.dir/testutil_security.cpp.o
[ 30%] Building CXX object tests/CMakeFiles/testutil-static.dir/testutil_unity.cpp.o
[ 30%] Building CXX object CMakeFiles/local_lat.dir/perf/local_lat.cpp.o
[ 30%] Building CXX object CMakeFiles/remote_lat.dir/perf/remote_lat.cpp.o
[ 30%] Linking CXX executable bin/local_lat
[ 30%] Linking CXX executable bin/remote_lat
[ 30%] Built target local_lat
[ 31%] Building CXX object CMakeFiles/local_thr.dir/perf/local_thr.cpp.o
[ 31%] Built target remote_lat
[ 32%] Linking CXX static library ../lib/libtestutil-static.a
[ 32%] Building CXX object CMakeFiles/remote_thr.dir/perf/remote_thr.cpp.o
[ 32%] Built target testutil-static
[ 33%] Building CXX object CMakeFiles/inproc_lat.dir/perf/inproc_lat.cpp.o
[ 33%] Linking CXX executable bin/local_thr
[ 34%] Linking CXX executable bin/remote_thr
[ 34%] Linking CXX executable bin/benchmark_radix_tree
[ 34%] Built target local_thr
[ 34%] Linking CXX executable bin/inproc_lat
[ 34%] Building CXX object CMakeFiles/inproc_thr.dir/perf/inproc_thr.cpp.o
[ 34%] Built target benchmark_radix_tree
[ 34%] Built target remote_thr
[ 34%] Building CXX object CMakeFiles/proxy_thr.dir/perf/proxy_thr.cpp.o
[ 34%] Building CXX object tests/CMakeFiles/testutil.dir/testutil.cpp.o
[ 34%] Built target inproc_lat
[ 34%] Building CXX object unittests/CMakeFiles/unittest_ypipe.dir/unittest_ypipe.cpp.o
[ 34%] Linking CXX executable bin/inproc_thr
[ 34%] Built target inproc_thr
[ 34%] Building CXX object unittests/CMakeFiles/unittest_poller.dir/unittest_poller.cpp.o
[ 35%] Linking CXX executable bin/proxy_thr
[ 36%] Building CXX object tests/CMakeFiles/testutil.dir/testutil_monitoring.cpp.o
[ 36%] Built target proxy_thr
[ 36%] Building CXX object unittests/CMakeFiles/unittest_mtrie.dir/unittest_mtrie.cpp.o
[ 36%] Linking CXX executable ../bin/unittest_ypipe
[ 36%] Building CXX object tests/CMakeFiles/testutil.dir/testutil_security.cpp.o
[ 36%] Built target unittest_ypipe
[ 36%] Building CXX object unittests/CMakeFiles/unittest_ip_resolver.dir/unittest_ip_resolver.cpp.o
[ 37%] Linking CXX executable ../bin/unittest_poller
[ 37%] Building CXX object tests/CMakeFiles/testutil.dir/testutil_unity.cpp.o
[ 37%] Built target unittest_poller
[ 37%] Building CXX object unittests/CMakeFiles/unittest_udp_address.dir/unittest_udp_address.cpp.o
[ 37%] Linking CXX static library ../lib/libtestutil.a
[ 37%] Built target testutil
[ 37%] Building CXX object unittests/CMakeFiles/unittest_radix_tree.dir/unittest_radix_tree.cpp.o
[ 38%] Linking CXX executable ../bin/unittest_udp_address
[ 38%] Linking CXX executable ../bin/unittest_mtrie
[ 39%] Linking CXX executable ../bin/unittest_ip_resolver
[ 39%] Built target unittest_udp_address
[ 39%] Building CXX object unittests/CMakeFiles/unittest_curve_encoding.dir/unittest_curve_encoding.cpp.o
[ 39%] Built target unittest_mtrie
[ 39%] Building CXX object tests/CMakeFiles/test_ancillaries.dir/test_ancillaries.cpp.o
[ 39%] Built target unittest_ip_resolver
[ 40%] Building CXX object tests/CMakeFiles/test_system.dir/test_system.cpp.o
[ 40%] Linking CXX executable ../bin/test_ancillaries
[ 40%] Linking CXX executable ../bin/test_system
[ 40%] Built target test_ancillaries
[ 41%] Building CXX object tests/CMakeFiles/test_pair_inproc.dir/test_pair_inproc.cpp.o
[ 41%] Built target test_system
[ 42%] Building CXX object tests/CMakeFiles/test_pair_tcp.dir/test_pair_tcp.cpp.o
[ 42%] Linking CXX executable ../bin/test_pair_inproc
[ 42%] Linking CXX executable ../bin/unittest_curve_encoding
[ 42%] Linking CXX executable ../bin/test_pair_tcp
[ 42%] Built target test_pair_inproc
[ 42%] Building CXX object tests/CMakeFiles/test_reqrep_inproc.dir/test_reqrep_inproc.cpp.o
[ 42%] Linking CXX executable ../bin/unittest_radix_tree
[ 42%] Built target test_pair_tcp
[ 42%] Building CXX object tests/CMakeFiles/test_reqrep_tcp.dir/test_reqrep_tcp.cpp.o
[ 42%] Built target unittest_curve_encoding
[ 43%] Building CXX object tests/CMakeFiles/test_hwm.dir/test_hwm.cpp.o
[ 44%] Linking CXX executable ../bin/test_reqrep_inproc
[ 44%] Built target unittest_radix_tree
[ 44%] Building CXX object tests/CMakeFiles/test_hwm_pubsub.dir/test_hwm_pubsub.cpp.o
[ 44%] Built target test_reqrep_inproc
[ 44%] Building CXX object tests/CMakeFiles/test_reqrep_device.dir/test_reqrep_device.cpp.o
[ 45%] Linking CXX executable ../bin/test_reqrep_tcp
[ 45%] Linking CXX executable ../bin/test_hwm
[ 45%] Built target test_reqrep_tcp
[ 46%] Building CXX object tests/CMakeFiles/test_sub_forward.dir/test_sub_forward.cpp.o
[ 46%] Built target test_hwm
[ 47%] Building CXX object tests/CMakeFiles/test_invalid_rep.dir/test_invalid_rep.cpp.o
[ 48%] Linking CXX executable ../bin/test_reqrep_device
[ 48%] Linking CXX executable ../bin/test_hwm_pubsub
[ 48%] Built target test_reqrep_device
[ 48%] Linking CXX executable ../bin/test_sub_forward
[ 49%] Building CXX object tests/CMakeFiles/test_msg_flags.dir/test_msg_flags.cpp.o
[ 49%] Linking CXX executable ../bin/test_invalid_rep
[ 49%] Built target test_hwm_pubsub
[ 49%] Building CXX object tests/CMakeFiles/test_msg_ffn.dir/test_msg_ffn.cpp.o
[ 49%] Built target test_sub_forward
[ 49%] Building CXX object tests/CMakeFiles/test_connect_resolve.dir/test_connect_resolve.cpp.o
[ 49%] Built target test_invalid_rep
[ 50%] Building CXX object tests/CMakeFiles/test_immediate.dir/test_immediate.cpp.o
[ 50%] Linking CXX executable ../bin/test_msg_flags
[ 50%] Linking CXX executable ../bin/test_msg_ffn
[ 50%] Linking CXX executable ../bin/test_connect_resolve
[ 50%] Built target test_msg_flags
[ 51%] Building CXX object tests/CMakeFiles/test_last_endpoint.dir/test_last_endpoint.cpp.o
[ 51%] Linking CXX executable ../bin/test_immediate
[ 51%] Built target test_msg_ffn
[ 52%] Building CXX object tests/CMakeFiles/test_term_endpoint.dir/test_term_endpoint.cpp.o
[ 52%] Built target test_connect_resolve
[ 52%] Building CXX object tests/CMakeFiles/test_router_mandatory.dir/test_router_mandatory.cpp.o
[ 52%] Built target test_immediate
[ 52%] Building CXX object tests/CMakeFiles/test_probe_router.dir/test_probe_router.cpp.o
[ 52%] Linking CXX executable ../bin/test_last_endpoint
[ 52%] Linking CXX executable ../bin/test_term_endpoint
[ 52%] Built target test_last_endpoint
[ 52%] Building CXX object tests/CMakeFiles/test_stream.dir/test_stream.cpp.o
[ 53%] Linking CXX executable ../bin/test_probe_router
[ 53%] Linking CXX executable ../bin/test_router_mandatory
[ 53%] Built target test_term_endpoint
[ 53%] Building CXX object tests/CMakeFiles/test_stream_empty.dir/test_stream_empty.cpp.o
[ 53%] Built target test_probe_router
[ 53%] Built target test_router_mandatory
[ 54%] Building CXX object tests/CMakeFiles/test_stream_disconnect.dir/test_stream_disconnect.cpp.o
[ 55%] Building CXX object tests/CMakeFiles/test_disconnect_inproc.dir/test_disconnect_inproc.cpp.o
[ 55%] Linking CXX executable ../bin/test_stream_empty
[ 55%] Linking CXX executable ../bin/test_stream
[ 55%] Built target test_stream_empty
[ 55%] Building CXX object tests/CMakeFiles/test_unbind_wildcard.dir/test_unbind_wildcard.cpp.o
[ 55%] Linking CXX executable ../bin/test_disconnect_inproc
[ 55%] Built target test_stream
[ 55%] Building CXX object tests/CMakeFiles/test_ctx_options.dir/test_ctx_options.cpp.o
[ 55%] Linking CXX executable ../bin/test_stream_disconnect
[ 55%] Built target test_disconnect_inproc
[ 55%] Building CXX object tests/CMakeFiles/test_ctx_destroy.dir/test_ctx_destroy.cpp.o
[ 55%] Built target test_stream_disconnect
[ 56%] Building CXX object tests/CMakeFiles/test_security_no_zap_handler.dir/test_security_no_zap_handler.cpp.o
[ 56%] Linking CXX executable ../bin/test_unbind_wildcard
[ 56%] Linking CXX executable ../bin/test_ctx_options
[ 56%] Built target test_unbind_wildcard
[ 56%] Building CXX object tests/CMakeFiles/test_security_null.dir/test_security_null.cpp.o
[ 56%] Linking CXX executable ../bin/test_ctx_destroy
[ 56%] Linking CXX executable ../bin/test_security_no_zap_handler
[ 56%] Built target test_ctx_options
[ 57%] Building CXX object tests/CMakeFiles/test_security_plain.dir/test_security_plain.cpp.o
[ 57%] Built target test_ctx_destroy
[ 57%] Built target test_security_no_zap_handler
[ 57%] Building CXX object tests/CMakeFiles/test_security_zap.dir/test_security_zap.cpp.o
[ 57%] Building CXX object tests/CMakeFiles/test_iov.dir/test_iov.cpp.o
[ 57%] Linking CXX executable ../bin/test_security_null
[ 57%] Linking CXX executable ../bin/test_security_plain
[ 57%] Built target test_security_null
[ 58%] Building CXX object tests/CMakeFiles/test_spec_req.dir/test_spec_req.cpp.o
[ 58%] Linking CXX executable ../bin/test_iov
[ 58%] Built target test_security_plain
[ 58%] Building CXX object tests/CMakeFiles/test_spec_rep.dir/test_spec_rep.cpp.o
[ 58%] Built target test_iov
[ 58%] Linking CXX executable ../bin/test_security_zap
[ 58%] Building CXX object tests/CMakeFiles/test_spec_dealer.dir/test_spec_dealer.cpp.o
[ 58%] Linking CXX executable ../bin/test_spec_req
[ 58%] Built target test_security_zap
[ 58%] Building CXX object tests/CMakeFiles/test_spec_router.dir/test_spec_router.cpp.o
[ 58%] Linking CXX executable ../bin/test_spec_rep
[ 58%] Built target test_spec_req
[ 59%] Building CXX object tests/CMakeFiles/test_spec_pushpull.dir/test_spec_pushpull.cpp.o
[ 59%] Linking CXX executable ../bin/test_spec_dealer
[ 59%] Built target test_spec_rep
[ 59%] Building CXX object tests/CMakeFiles/test_req_correlate.dir/test_req_correlate.cpp.o
[ 59%] Linking CXX executable ../bin/test_spec_router
[ 59%] Built target test_spec_dealer
[ 59%] Building CXX object tests/CMakeFiles/test_req_relaxed.dir/test_req_relaxed.cpp.o
[ 60%] Linking CXX executable ../bin/test_req_correlate
[ 60%] Built target test_spec_router
[ 60%] Building CXX object tests/CMakeFiles/test_conflate.dir/test_conflate.cpp.o
[ 60%] Linking CXX executable ../bin/test_spec_pushpull
[ 60%] Built target test_req_correlate
[ 60%] Building CXX object tests/CMakeFiles/test_inproc_connect.dir/test_inproc_connect.cpp.o
[ 60%] Linking CXX executable ../bin/test_req_relaxed
[ 60%] Linking CXX executable ../bin/test_conflate
[ 60%] Built target test_spec_pushpull
[ 60%] Building CXX object tests/CMakeFiles/test_issue_566.dir/test_issue_566.cpp.o
[ 60%] Built target test_req_relaxed
[ 60%] Building CXX object tests/CMakeFiles/test_shutdown_stress.dir/test_shutdown_stress.cpp.o
[ 60%] Built target test_conflate
[ 60%] Building CXX object tests/CMakeFiles/test_timeo.dir/test_timeo.cpp.o
[ 60%] Linking CXX executable ../bin/test_inproc_connect
[ 60%] Linking CXX executable ../bin/test_issue_566
[ 60%] Linking CXX executable ../bin/test_shutdown_stress
[ 60%] Linking CXX executable ../bin/test_timeo
[ 60%] Built target test_inproc_connect
[ 60%] Built target test_issue_566
[ 60%] Building CXX object tests/CMakeFiles/test_many_sockets.dir/test_many_sockets.cpp.o
[ 60%] Building CXX object tests/CMakeFiles/test_diffserv.dir/test_diffserv.cpp.o
[ 60%] Built target test_shutdown_stress
[ 60%] Building CXX object tests/CMakeFiles/test_connect_rid.dir/test_connect_rid.cpp.o
[ 60%] Built target test_timeo
[ 60%] Building CXX object tests/CMakeFiles/test_xpub_nodrop.dir/test_xpub_nodrop.cpp.o
[ 60%] Linking CXX executable ../bin/test_diffserv
[ 61%] Linking CXX executable ../bin/test_xpub_nodrop
[ 62%] Linking CXX executable ../bin/test_connect_rid
[ 62%] Built target test_diffserv
[ 62%] Building CXX object tests/CMakeFiles/test_pub_invert_matching.dir/test_pub_invert_matching.cpp.o
[ 62%] Linking CXX executable ../bin/test_many_sockets
[ 62%] Built target test_xpub_nodrop
[ 62%] Built target test_connect_rid
[ 63%] Building CXX object tests/CMakeFiles/test_setsockopt.dir/test_setsockopt.cpp.o
[ 64%] Building CXX object tests/CMakeFiles/test_sockopt_hwm.dir/test_sockopt_hwm.cpp.o
[ 64%] Built target test_many_sockets
[ 64%] Building CXX object tests/CMakeFiles/test_heartbeats.dir/test_heartbeats.cpp.o
[ 65%] Linking CXX executable ../bin/test_pub_invert_matching
[ 65%] Built target test_pub_invert_matching
[ 65%] Linking CXX executable ../bin/test_setsockopt
[ 65%] Building CXX object tests/CMakeFiles/test_atomics.dir/test_atomics.cpp.o
[ 65%] Linking CXX executable ../bin/test_sockopt_hwm
[ 65%] Built target test_setsockopt
[ 65%] Built target test_sockopt_hwm
[ 65%] Building CXX object tests/CMakeFiles/test_bind_src_address.dir/test_bind_src_address.cpp.o
[ 65%] Building CXX object tests/CMakeFiles/test_capabilities.dir/test_capabilities.cpp.o
[ 65%] Linking CXX executable ../bin/test_atomics
[ 65%] Linking CXX executable ../bin/test_heartbeats
[ 66%] Linking CXX executable ../bin/test_bind_src_address
[ 66%] Built target test_heartbeats
[ 66%] Built target test_atomics
[ 66%] Building CXX object tests/CMakeFiles/test_router_handover.dir/test_router_handover.cpp.o
[ 68%] Linking CXX executable ../bin/test_capabilities
[ 68%] Building CXX object tests/CMakeFiles/test_metadata.dir/test_metadata.cpp.o
[ 68%] Built target test_bind_src_address
[ 69%] Building CXX object tests/CMakeFiles/test_srcfd.dir/test_srcfd.cpp.o
[ 69%] Built target test_capabilities
[ 69%] Building CXX object tests/CMakeFiles/test_stream_timeout.dir/test_stream_timeout.cpp.o
[ 70%] Linking CXX executable ../bin/test_router_handover
[ 70%] Linking CXX executable ../bin/test_metadata
[ 70%] Linking CXX executable ../bin/test_srcfd
[ 70%] Built target test_router_handover
[ 70%] Building CXX object tests/CMakeFiles/test_xpub_manual.dir/test_xpub_manual.cpp.o
[ 70%] Built target test_metadata
[ 70%] Linking CXX executable ../bin/test_stream_timeout
[ 70%] Building CXX object tests/CMakeFiles/test_xpub_topic.dir/test_xpub_topic.cpp.o
[ 70%] Built target test_srcfd
[ 70%] Building CXX object tests/CMakeFiles/test_xpub_welcome_msg.dir/test_xpub_welcome_msg.cpp.o
[ 70%] Built target test_stream_timeout
[ 70%] Building CXX object tests/CMakeFiles/test_xpub_verbose.dir/test_xpub_verbose.cpp.o
[ 70%] Linking CXX executable ../bin/test_xpub_topic
[ 70%] Linking CXX executable ../bin/test_xpub_welcome_msg
[ 70%] Built target test_xpub_topic
[ 70%] Building CXX object tests/CMakeFiles/test_base85.dir/test_base85.cpp.o
[ 70%] Built target test_xpub_welcome_msg
[ 71%] Linking CXX executable ../bin/test_xpub_manual
[ 71%] Building CXX object tests/CMakeFiles/test_bind_after_connect_tcp.dir/test_bind_after_connect_tcp.cpp.o
[ 72%] Linking CXX executable ../bin/test_xpub_verbose
[ 72%] Built target test_xpub_manual
[ 73%] Building CXX object tests/CMakeFiles/test_sodium.dir/test_sodium.cpp.o
[ 73%] Built target test_xpub_verbose
[ 74%] Building CXX object tests/CMakeFiles/test_monitor.dir/test_monitor.cpp.o
[ 74%] Linking CXX executable ../bin/test_bind_after_connect_tcp
[ 75%] Linking CXX executable ../bin/test_base85
[ 75%] Built target test_bind_after_connect_tcp
[ 75%] Linking CXX executable ../bin/test_sodium
[ 75%] Building CXX object tests/CMakeFiles/test_socket_null.dir/test_socket_null.cpp.o
[ 75%] Built target test_base85
[ 75%] Building CXX object tests/CMakeFiles/test_reconnect_ivl.dir/test_reconnect_ivl.cpp.o
[ 75%] Built target test_sodium
[ 75%] Building CXX object tests/CMakeFiles/test_reconnect_options.dir/test_reconnect_options.cpp.o
[ 75%] Linking CXX executable ../bin/test_monitor
[ 75%] Linking CXX executable ../bin/test_socket_null
[ 76%] Linking CXX executable ../bin/test_reconnect_ivl
[ 76%] Built target test_monitor
[ 76%] Building CXX object tests/CMakeFiles/test_tcp_accept_filter.dir/test_tcp_accept_filter.cpp.o
[ 76%] Built target test_socket_null
[ 76%] Built target test_reconnect_ivl
[ 76%] Building CXX object tests/CMakeFiles/test_mock_pub_sub.dir/test_mock_pub_sub.cpp.o
[ 76%] Building CXX object tests/CMakeFiles/test_security_gssapi.dir/test_security_gssapi.cpp.o
[ 76%] Linking CXX executable ../bin/test_reconnect_options
[ 76%] Built target test_reconnect_options
[ 76%] Building CXX object tests/CMakeFiles/test_socks.dir/test_socks.cpp.o
[ 76%] Linking CXX executable ../bin/test_tcp_accept_filter
[ 76%] Linking CXX executable ../bin/test_mock_pub_sub
[ 76%] Linking CXX executable ../bin/test_security_gssapi
[ 76%] Built target test_tcp_accept_filter
[ 76%] Building CXX object tests/CMakeFiles/test_connect_null_fuzzer.dir/test_connect_null_fuzzer.cpp.o
[ 76%] Built target test_mock_pub_sub
[ 76%] Building CXX object tests/CMakeFiles/test_bind_null_fuzzer.dir/test_bind_null_fuzzer.cpp.o
[ 76%] Built target test_security_gssapi
[ 76%] Building CXX object tests/CMakeFiles/test_connect_fuzzer.dir/test_connect_fuzzer.cpp.o
[ 77%] Linking CXX executable ../bin/test_connect_null_fuzzer
[ 77%] Linking CXX executable ../bin/test_bind_null_fuzzer
[ 77%] Built target test_connect_null_fuzzer
[ 77%] Building CXX object tests/CMakeFiles/test_bind_fuzzer.dir/test_bind_fuzzer.cpp.o
[ 77%] Built target test_bind_null_fuzzer
[ 78%] Building CXX object tests/CMakeFiles/test_ipc_wildcard.dir/test_ipc_wildcard.cpp.o
[ 78%] Linking CXX executable ../bin/test_connect_fuzzer
[ 78%] Linking CXX executable ../bin/test_ipc_wildcard
[ 78%] Built target test_connect_fuzzer
[ 78%] Building CXX object tests/CMakeFiles/test_pair_ipc.dir/test_pair_ipc.cpp.o
[ 78%] Linking CXX executable ../bin/test_socks
[ 78%] Built target test_ipc_wildcard
[ 78%] Building CXX object tests/CMakeFiles/test_reqrep_ipc.dir/test_reqrep_ipc.cpp.o
[ 79%] Linking CXX executable ../bin/test_bind_fuzzer
[ 79%] Built target test_socks
[ 79%] Building CXX object tests/CMakeFiles/test_rebind_ipc.dir/test_rebind_ipc.cpp.o
[ 79%] Linking CXX executable ../bin/test_reqrep_ipc
[ 79%] Built target test_bind_fuzzer
[ 79%] Building CXX object tests/CMakeFiles/test_proxy.dir/test_proxy.cpp.o
[ 79%] Linking CXX executable ../bin/test_rebind_ipc
[ 79%] Built target test_reqrep_ipc
[ 79%] Building CXX object tests/CMakeFiles/test_proxy_hwm.dir/test_proxy_hwm.cpp.o
[ 79%] Linking CXX executable ../bin/test_pair_ipc
[ 79%] Built target test_rebind_ipc
[ 79%] Building CXX object tests/CMakeFiles/test_proxy_single_socket.dir/test_proxy_single_socket.cpp.o
[ 79%] Built target test_pair_ipc
[ 79%] Building CXX object tests/CMakeFiles/test_proxy_steerable.dir/test_proxy_steerable.cpp.o
[ 79%] Linking CXX executable ../bin/test_proxy
[ 80%] Linking CXX executable ../bin/test_proxy_hwm
[ 80%] Linking CXX executable ../bin/test_proxy_single_socket
[ 80%] Built target test_proxy
[ 80%] Building CXX object tests/CMakeFiles/test_proxy_terminate.dir/test_proxy_terminate.cpp.o
[ 80%] Built target test_proxy_hwm
[ 81%] Building CXX object tests/CMakeFiles/test_getsockopt_memset.dir/test_getsockopt_memset.cpp.o
[ 81%] Built target test_proxy_single_socket
[ 82%] Building CXX object tests/CMakeFiles/test_filter_ipc.dir/test_filter_ipc.cpp.o
[ 83%] Linking CXX executable ../bin/test_proxy_steerable
[ 83%] Linking CXX executable ../bin/test_proxy_terminate
[ 83%] Linking CXX executable ../bin/test_getsockopt_memset
[ 83%] Built target test_proxy_steerable
[ 84%] Building CXX object tests/CMakeFiles/test_stream_exceeds_buffer.dir/test_stream_exceeds_buffer.cpp.o
[ 84%] Linking CXX executable ../bin/test_filter_ipc
[ 84%] Built target test_proxy_terminate
[ 84%] Building CXX object tests/CMakeFiles/test_router_mandatory_hwm.dir/test_router_mandatory_hwm.cpp.o
[ 84%] Built target test_getsockopt_memset
[ 84%] Building CXX object tests/CMakeFiles/test_use_fd.dir/test_use_fd.cpp.o
[ 84%] Built target test_filter_ipc
[ 84%] Building CXX object tests/CMakeFiles/test_zmq_poll_fd.dir/test_zmq_poll_fd.cpp.o
[ 84%] Linking CXX executable ../bin/test_stream_exceeds_buffer
[ 85%] Linking CXX executable ../bin/test_router_mandatory_hwm
[ 86%] Linking CXX executable ../bin/test_use_fd
[ 86%] Built target test_stream_exceeds_buffer
[ 86%] Building CXX object tests/CMakeFiles/test_fork.dir/test_fork.cpp.o
[ 86%] Linking CXX executable ../bin/test_zmq_poll_fd
[ 86%] Built target test_router_mandatory_hwm
[ 86%] Building CXX object tests/CMakeFiles/test_abstract_ipc.dir/test_abstract_ipc.cpp.o
[ 86%] Built target test_use_fd
[ 86%] Building CXX object tests/CMakeFiles/test_address_tipc.dir/test_address_tipc.cpp.o
[ 86%] Built target test_zmq_poll_fd
[ 86%] Building CXX object tests/CMakeFiles/test_pair_tipc.dir/test_pair_tipc.cpp.o
[ 86%] Linking CXX executable ../bin/test_fork
[ 86%] Linking CXX executable ../bin/test_abstract_ipc
[ 87%] Linking CXX executable ../bin/test_address_tipc
[ 87%] Built target test_fork
[ 87%] Linking CXX executable ../bin/test_pair_tipc
[ 87%] Building CXX object tests/CMakeFiles/test_reqrep_device_tipc.dir/test_reqrep_device_tipc.cpp.o
[ 87%] Built target test_abstract_ipc
[ 87%] Building CXX object tests/CMakeFiles/test_reqrep_tipc.dir/test_reqrep_tipc.cpp.o
[ 87%] Built target test_address_tipc
[ 87%] Built target test_pair_tipc
[ 87%] Building CXX object tests/CMakeFiles/test_router_mandatory_tipc.dir/test_router_mandatory_tipc.cpp.o
[ 87%] Building CXX object tests/CMakeFiles/test_sub_forward_tipc.dir/test_sub_forward_tipc.cpp.o
[ 87%] Linking CXX executable ../bin/test_reqrep_tipc
[ 87%] Linking CXX executable ../bin/test_reqrep_device_tipc
[ 87%] Linking CXX executable ../bin/test_router_mandatory_tipc
[ 87%] Linking CXX executable ../bin/test_sub_forward_tipc
[ 87%] Built target test_reqrep_tipc
[ 87%] Building CXX object tests/CMakeFiles/test_connect_delay_tipc.dir/test_connect_delay_tipc.cpp.o
[ 87%] Built target test_reqrep_device_tipc
[ 88%] Building CXX object tests/CMakeFiles/test_shutdown_stress_tipc.dir/test_shutdown_stress_tipc.cpp.o
[ 88%] Built target test_router_mandatory_tipc
[ 88%] Building CXX object tests/CMakeFiles/test_term_endpoint_tipc.dir/test_term_endpoint_tipc.cpp.o
[ 88%] Built target test_sub_forward_tipc
[ 88%] Building CXX object tests/CMakeFiles/test_poller.dir/test_poller.cpp.o
[ 88%] Linking CXX executable ../bin/test_shutdown_stress_tipc
[ 89%] Linking CXX executable ../bin/test_connect_delay_tipc
[ 89%] Linking CXX executable ../bin/test_term_endpoint_tipc
[ 89%] Built target test_shutdown_stress_tipc
[ 89%] Building CXX object tests/CMakeFiles/test_thread_safe.dir/test_thread_safe.cpp.o
[ 89%] Built target test_connect_delay_tipc
[ 89%] Building CXX object tests/CMakeFiles/test_client_server.dir/test_client_server.cpp.o
[ 89%] Built target test_term_endpoint_tipc
[ 89%] Building CXX object tests/CMakeFiles/test_timers.dir/test_timers.cpp.o
[ 90%] Linking CXX executable ../bin/test_thread_safe
[ 91%] Linking CXX executable ../bin/test_client_server
[ 92%] Linking CXX executable ../bin/test_timers
[ 92%] Built target test_thread_safe
[ 92%] Building CXX object tests/CMakeFiles/test_radio_dish.dir/test_radio_dish.cpp.o
[ 92%] Built target test_client_server
[ 92%] Building CXX object tests/CMakeFiles/test_scatter_gather.dir/test_scatter_gather.cpp.o
[ 92%] Linking CXX executable ../bin/test_poller
[ 92%] Built target test_timers
[ 93%] Building CXX object tests/CMakeFiles/test_dgram.dir/test_dgram.cpp.o
[ 93%] Linking CXX executable ../bin/test_scatter_gather
[ 93%] Built target test_poller
[ 93%] Building CXX object tests/CMakeFiles/test_app_meta.dir/test_app_meta.cpp.o
[ 93%] Linking CXX executable ../bin/test_dgram
[ 93%] Built target test_scatter_gather
[ 94%] Linking CXX executable ../bin/test_radio_dish
[ 94%] Building CXX object tests/CMakeFiles/test_router_notify.dir/test_router_notify.cpp.o
[ 94%] Built target test_dgram
[ 94%] Building CXX object tests/CMakeFiles/test_xpub_manual_last_value.dir/test_xpub_manual_last_value.cpp.o
[ 95%] Linking CXX executable ../bin/test_app_meta
[ 95%] Built target test_radio_dish
[ 95%] Building CXX object tests/CMakeFiles/test_peer.dir/test_peer.cpp.o
[ 95%] Built target test_app_meta
[ 95%] Building CXX object tests/CMakeFiles/test_msg_init.dir/test_msg_init.cpp.o
[ 96%] Linking CXX executable ../bin/test_router_notify
[ 97%] Linking CXX executable ../bin/test_peer
[ 97%] Built target test_router_notify
[ 97%] Building CXX object tests/CMakeFiles/test_channel.dir/test_channel.cpp.o
[ 97%] Built target test_peer
[ 97%] Linking CXX executable ../bin/test_msg_init
[ 98%] Building CXX object tests/CMakeFiles/test_hello_msg.dir/test_hello_msg.cpp.o
[ 98%] Linking CXX executable ../bin/test_xpub_manual_last_value
[ 98%] Linking CXX executable ../bin/test_channel
[ 98%] Built target test_msg_init
[ 98%] Building CXX object tests/CMakeFiles/test_disconnect_msg.dir/test_disconnect_msg.cpp.o
[ 98%] Built target test_xpub_manual_last_value
[ 98%] Building CXX object tests/CMakeFiles/test_hiccup_msg.dir/test_hiccup_msg.cpp.o
[ 98%] Linking CXX executable ../bin/test_hello_msg
[ 98%] Built target test_channel
[ 98%] Building CXX object tests/CMakeFiles/test_zmq_ppoll_fd.dir/test_zmq_ppoll_fd.cpp.o
[ 98%] Built target test_hello_msg
[ 98%] Linking CXX executable ../bin/test_disconnect_msg
[ 98%] Building CXX object tests/CMakeFiles/test_xsub_verbose.dir/test_xsub_verbose.cpp.o
[ 98%] Linking CXX executable ../bin/test_hiccup_msg
[ 99%] Linking CXX executable ../bin/test_zmq_ppoll_fd
[ 99%] Built target test_disconnect_msg
[ 99%] Building CXX object tests/CMakeFiles/test_pubsub_topics_count.dir/test_pubsub_topics_count.cpp.o
[ 99%] Built target test_hiccup_msg
[ 99%] Building CXX object tests/CMakeFiles/test_zmq_ppoll_signals.dir/test_zmq_ppoll_signals.cpp.o
[100%] Linking CXX executable ../bin/test_xsub_verbose
[100%] Built target test_zmq_ppoll_fd
[100%] Building CXX object tests/CMakeFiles/test_busy_poll.dir/test_busy_poll.cpp.o
[100%] Built target test_xsub_verbose
[100%] Building CXX object tests/CMakeFiles/test_ws_transport.dir/test_ws_transport.cpp.o
[100%] Linking CXX executable ../bin/test_pubsub_topics_count
[100%] Linking CXX executable ../bin/test_zmq_ppoll_signals
[100%] Linking CXX executable ../bin/test_busy_poll
[100%] Built target test_pubsub_topics_count
[100%] Built target test_zmq_ppoll_signals
[100%] Built target test_busy_poll
[100%] Linking CXX executable ../bin/test_ws_transport
[100%] Built target test_ws_transport
Install the project...
-- Install configuration: "Release"
-- Installing: /usr/local/lib/pkgconfig/libzmq.pc
-- Installing: /usr/local/bin/local_lat
-- Set non-toolchain portion of runtime path of "/usr/local/bin/local_lat" to ""
-- Installing: /usr/local/bin/remote_lat
-- Set non-toolchain portion of runtime path of "/usr/local/bin/remote_lat" to ""
-- Installing: /usr/local/bin/local_thr
-- Set non-toolchain portion of runtime path of "/usr/local/bin/local_thr" to ""
-- Installing: /usr/local/bin/remote_thr
-- Set non-toolchain portion of runtime path of "/usr/local/bin/remote_thr" to ""
-- Installing: /usr/local/bin/inproc_lat
-- Set non-toolchain portion of runtime path of "/usr/local/bin/inproc_lat" to ""
-- Installing: /usr/local/bin/inproc_thr
-- Set non-toolchain portion of runtime path of "/usr/local/bin/inproc_thr" to ""
-- Installing: /usr/local/bin/proxy_thr
-- Set non-toolchain portion of runtime path of "/usr/local/bin/proxy_thr" to ""
-- Installing: /usr/local/lib/libzmq.so.5.2.6
-- Installing: /usr/local/lib/libzmq.so.5
-- Installing: /usr/local/lib/libzmq.so
-- Installing: /usr/local/include/zmq.h
-- Installing: /usr/local/include/zmq_utils.h
-- Installing: /usr/local/lib/libzmq.a
-- Up-to-date: /usr/local/include/zmq.h
-- Up-to-date: /usr/local/include/zmq_utils.h
-- Installing: /usr/local/share/zmq/AUTHORS.txt
-- Installing: /usr/local/share/zmq/LICENSE.txt
-- Installing: /usr/local/share/zmq/NEWS.txt
-- Installing: /usr/local/lib/cmake/ZeroMQ/ZeroMQTargets.cmake
-- Installing: /usr/local/lib/cmake/ZeroMQ/ZeroMQTargets-release.cmake
-- Installing: /usr/local/lib/cmake/ZeroMQ/ZeroMQConfig.cmake
-- Installing: /usr/local/lib/cmake/ZeroMQ/ZeroMQConfigVersion.cmake
2.3安装cppzmq库
- Build cppzmq via cmake. This does an out of source build and installs the build files
git clone https://github.com/zeromq/cppzmq.gitcd cppzmqmkdir buildcd buildcmake ..orcmake -DCPPZMQ_BUILD_TESTS=OFF ..to skip building testssudo make -j4 install
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/libzmq/build$ cd ..
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/libzmq$ cd ..
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project$ cd cppzmq/
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/cppzmq$ mkdir build
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/cppzmq$ cd build/
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/cppzmq/build$ cmake ..
-- Detected CPPZMQ Version - 4.11.0
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- cppzmq v4.11.0
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
[ 11%] Creating directories for 'catch2-populate'
[ 22%] Performing download step (git clone) for 'catch2-populate'
Cloning into 'catch2-src'...
error: RPC failed; curl 16 Error in the HTTP2 framing layer
fatal: expected flush after ref listing
Cloning into 'catch2-src'...
fatal: unable to access 'https://github.com/catchorg/Catch2.git/': Failed to connect to github.com port 443 after 130307 ms: Connection timed out
Cloning into 'catch2-src'...
fatal: unable to access 'https://github.com/catchorg/Catch2.git/': Failed to connect to github.com port 443 after 131041 ms: Connection timed out
Had to git clone more than once: 3 times.
CMake Error at catch2-subbuild/catch2-populate-prefix/tmp/catch2-populate-gitclone.cmake:50 (message):
Failed to clone repository: 'https://github.com/catchorg/Catch2.git'
gmake[2]: *** [CMakeFiles/catch2-populate.dir/build.make:102: catch2-populate-prefix/src/catch2-populate-stamp/catch2-populate-download] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:87: CMakeFiles/catch2-populate.dir/all] Error 2
gmake: *** [Makefile:91: all] Error 2
CMake Error at /usr/local/share/cmake-4.1/Modules/FetchContent.cmake:1918 (message):
Build step for catch2 failed: 2
Call Stack (most recent call first):
/usr/local/share/cmake-4.1/Modules/FetchContent.cmake:1609 (__FetchContent_populateSubbuild)
/usr/local/share/cmake-4.1/Modules/FetchContent.cmake:2145:EVAL:2 (__FetchContent_doPopulation)
/usr/local/share/cmake-4.1/Modules/FetchContent.cmake:2145 (cmake_language)
/usr/local/share/cmake-4.1/Modules/FetchContent.cmake:2384 (__FetchContent_Populate)
tests/CMakeLists.txt:13 (FetchContent_MakeAvailable)
-- Configuring incomplete, errors occurred!
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/cppzmq/build$ cmake -DCPPZMQ_BUILD_TESTS=OFF ..
-- Detected CPPZMQ Version - 4.11.0
-- cppzmq v4.11.0
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/Tronlong/mmcblk0p8/project_code/project/cppzmq/build
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/cppzmq/build$ sudo make -j4 install
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/include/zmq.hpp
-- Installing: /usr/local/include/zmq_addon.hpp
-- Installing: /usr/local/lib/pkgconfig/cppzmq.pc
-- Installing: /usr/local/share/cmake/cppzmq/cppzmqTargets.cmake
-- Installing: /usr/local/share/cmake/cppzmq/cppzmqConfig.cmake
-- Installing: /usr/local/share/cmake/cppzmq/cppzmqConfigVersion.cmake
-- Installing: /usr/local/share/cmake/cppzmq/libzmq-pkg-config/FindZeroMQ.cmake
- Alternatively, build cppzmq via vcpkg. This does an out of source build and installs the build files
git clone https://github.com/Microsoft/vcpkg.gitcd vcpkg./bootstrap-vcpkg.sh(bootstrap-vcpkg.bat for Powershell)./vcpkg integrate install./vcpkg install cppzmq
📡 3、发布-订阅模式(PUB/SUB)
🧩 模型介绍
发布者(Publisher) 持续发布主题消息;Win11的VS2022环境
订阅者(Subscriber) 根据主题过滤并接收对应内容。Ubuntu22.04的RK3576环境
🖥️ 示例 1:Publisher 发送多种主题消息
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "zmq.h"
#include <string>
#include <thread>
#include <atomic>
#include <iostream>
int main()
{
void* context = zmq_ctx_new();
assert(context != NULL);
void* publisher = zmq_socket(context, ZMQ_PUB);
assert(publisher != NULL);
int ret = zmq_bind(publisher, "tcp://*:5555");
assert(ret == 0);
int i = 0;
while (1)
{
char szBuf[1024] = { 0 };
snprintf(szBuf, sizeof(szBuf), "server i=%d", i);
ret = zmq_send(publisher, szBuf, strlen(szBuf) + 1, 0);
i++;
printf("[SENT szBuf] %s\n", szBuf);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
zmq_close(publisher);
zmq_ctx_destroy(context);
return 0;
}
直接Debug运行
🖥️ 示例 2:Subscriber 订阅并打印消息
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include "zmq.h"
int main()
{
printf("Hello world!\n");
void* context = zmq_ctx_new();
assert(context != NULL);
void* subscriber = zmq_socket(context, ZMQ_SUB);
assert(subscriber != NULL);
int ret = zmq_connect(subscriber, "tcp://192.168.170.53:5555");
assert(ret == 0);
ret = zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, "", 0);
assert(ret == 0);
while(1)
{
printf("into while\n");
char szBuf[1024] = {0};
ret = zmq_recv(subscriber, szBuf, sizeof(szBuf) - 1, 0);
if (ret > 0)
{
printf("%s\n", szBuf);
}
}
zmq_close(subscriber);
zmq_ctx_destroy(context);
return 0;
}
请注意一下ip地址,我现在
| 主机 | 从机 | |
|---|---|---|
| 系统 | win11 | Ubuntu22.04 |
| 名称 | Publisher | Subscriber |
| 地址 | 192.168.170.53 | 192.168.170.77 |
在代码中需要注意一下关于192.168.170.53地址,你都需要自己替换到目标服务器地址哦🤣🤣🤣🤣
int ret = zmq_connect(subscriber, "tcp://192.168.170.53:5555");
Cmake文件配置
cmake_minimum_required(VERSION 3.10)
project(zmq_client)
# 查找 ZeroMQ 库
find_library(ZMQ_LIBRARY NAMES zmq)
find_path(ZMQ_INCLUDE_DIR zmq.h)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(EXE_NAME zmq_client)
file(GLOB SOURCES "src/*.cpp")
include_directories(include)
add_executable(${EXE_NAME} ${SOURCES})
# 链接 ZeroMQ 库
target_link_libraries(zmq_client ${ZMQ_LIBRARY})
target_include_directories(zmq_client PRIVATE ${ZMQ_INCLUDE_DIR})
运行另外个终端,编译运行指令
mkdir build&&cd build
cmake ..&&make
./zmp_client
Ctrl+C停止运行
启动下面的程序就可以收到数据啦
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/zmp_client/build$ make clean
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/zmp_client/build$ cmake ..&make
[1] 203962
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/Tronlong/mmcblk0p8/project_code/project/zmp_client/build
[ 25%] Building CXX object CMakeFiles/zmq_client.dir/src/main.cpp.o
[ 50%] Building CXX object CMakeFiles/zmq_client.dir/src/main1.cpp.o
[ 75%] Building CXX object CMakeFiles/zmq_client.dir/src/main2.cpp.o
[100%] Linking CXX executable zmq_client
[100%] Built target zmq_client
[1]+ Done cmake ..
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/zmp_client/build$ ./zmq_client
Hello world!
into while
server i=28
into while
server i=29
into while
server i=30
into while
server i=31
into while
server i=32
into while
server i=33
into while
server i=34
into while
server i=35
into while
server i=36
🔁 四、双向发布订阅(两个节点互发)
在某些设备(如无人船)中,既需要发布传感器数据,也要接收控制命令。
可以让两个进程各自绑定 PUB/SUB 套接字,互为发布者与订阅者。
🌐 进程 1:Host 节点(发布命令 / 订阅传感器)
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "zmq.h"
#include <string>
#include <thread>
#include <atomic>
#include <iostream>
#include <chrono>
std::atomic<bool> g_running{ true };
// 接收数据线程函数
void recv_thread(void* subscriber) {
while (g_running) {
char szBuf[1024] = { 0 };
int ret = zmq_recv(subscriber, szBuf, sizeof(szBuf) - 1, 0);
if (ret > 0) {
printf("Received data: %s\n", szBuf);
}
else {
// 处理错误或超时,这里我们简单等待
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
}
int main() {
void* context = zmq_ctx_new();
assert(context != NULL);
// 创建发布者socket(发送命令)
void* publisher = zmq_socket(context, ZMQ_PUB);
assert(publisher != NULL);
int ret = zmq_bind(publisher, "tcp://*:5555");
assert(ret == 0);
// 创建订阅者socket(接收数据)
void* subscriber = zmq_socket(context, ZMQ_SUB);
assert(subscriber != NULL);
ret = zmq_bind(subscriber, "tcp://*:5556");
assert(ret == 0);
ret = zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, "", 0);
assert(ret == 0);
// 启动接收线程
std::thread t(recv_thread, subscriber);
// 主循环用于发送命令
int i = 0;
while (g_running) {
char szBuf[1024] = { 0 };
snprintf(szBuf, sizeof(szBuf), "Command %d", i);
ret = zmq_send(publisher, szBuf, strlen(szBuf) + 1, 0);
if (ret < 0) {
printf("Send failed: %s\n", zmq_strerror(errno));
}
else {
printf("Sent command: %s\n", szBuf);
}
i++;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
// 清理
t.join();
zmq_close(publisher);
zmq_close(subscriber);
zmq_ctx_destroy(context);
return 0;
}
直接Debug走起,如果启动下面线程就可以收到数据

Received data: SENSOR_DATA_0 from client
Received data: HEARTBEAT_0
Sent command: Command 32
Sent command: Command 33
Received data: SENSOR_DATA_1 from client
Received data: HEARTBEAT_1
Sent command: Command 34
Sent command: Command 35
Received data: SENSOR_DATA_2 from client
Received data: HEARTBEAT_2
Sent command: Command 36
Sent command: Command 37
Received data: SENSOR_DATA_3 from client
Received data: HEARTBEAT_3
Sent command: Command 38
Sent command: Command 39
Received data: SENSOR_DATA_4 from client
Received data: HEARTBEAT_4
Sent command: Command 40
🌐 进程 2:Device 节点(发布传感器 / 订阅命令)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h> // 添加这个头文件
#include <signal.h>
#include "zmq.h"
#include <atomic>
#include <thread>
#include <iostream> // 建议也添加这个
#include <chrono> // 建议也添加这个
std::atomic<bool> g_running{ true };
void signal_handler(int sig) {
printf("Received signal %d, shutting down...\n", sig);
g_running = false;
}
// 接收线程函数 - 接收服务器命令
void recv_commands_thread(void* subscriber) {
printf("Command receiver thread started\n");
while (g_running) {
char szBuf[1024] = { 0 };
int ret = zmq_recv(subscriber, szBuf, sizeof(szBuf) - 1, 0);
if (ret > 0) {
printf("[RECV FROM SERVER] %s\n", szBuf);
// 处理接收到的命令
if (strstr(szBuf, "COMMAND") != NULL) {
printf(" -> Processing command...\n");
} else if (strstr(szBuf, "SERVER_DATA") != NULL) {
printf(" -> Received server data\n");
}
} else {
// 非阻塞接收,短暂延迟后继续
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
printf("Command receiver thread stopped\n");
}
int main() {
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
printf("Starting ZMQ Client (Bidirectional)...\n");
printf("Client IP: 192.168.170.77\n");
printf("Connecting to server: 192.168.170.53\n");
printf("Port 5555: Receive commands from server\n");
printf("Port 5556: Send data to server\n");
void* context = zmq_ctx_new();
assert(context != NULL);
// 创建订阅者socket - 接收服务器命令
void* command_subscriber = zmq_socket(context, ZMQ_SUB);
assert(command_subscriber != NULL);
int ret = zmq_connect(command_subscriber, "tcp://192.168.170.53:5555");
assert(ret == 0);
ret = zmq_setsockopt(command_subscriber, ZMQ_SUBSCRIBE, "", 0);
assert(ret == 0);
// 设置非阻塞接收
int timeout = 100; // 100ms timeout
zmq_setsockopt(command_subscriber, ZMQ_RCVTIMEO, &timeout, sizeof(timeout));
printf("Command subscriber connected to tcp://192.168.170.53:5555\n");
// 创建发布者socket - 发送数据到服务器
void* data_publisher = zmq_socket(context, ZMQ_PUB);
assert(data_publisher != NULL);
ret = zmq_connect(data_publisher, "tcp://192.168.170.53:5556");
assert(ret == 0);
// 等待连接稳定(PUB-SUB模式需要)
printf("Waiting for connection stabilization...\n");
sleep(2);
printf("Data publisher connected to tcp://192.168.170.53:5556\n");
printf("Client started successfully!\n");
// 启动命令接收线程
std::thread command_thread(recv_commands_thread, command_subscriber);
// 主循环 - 发送数据到服务器
int sensor_count = 0;
int heartbeat_count = 0;
printf("Starting data transmission...\n");
while (g_running) {
// 发送传感器数据
char sensor_buf[1024] = { 0 };
snprintf(sensor_buf, sizeof(sensor_buf), "SENSOR_DATA_%d from client", sensor_count++);
ret = zmq_send(data_publisher, sensor_buf, strlen(sensor_buf) + 1, 0); // 现在 strlen 可以正常使用了
printf("[SENT TO SERVER] %s\n", sensor_buf);
// 发送心跳
char heartbeat_buf[1024] = { 0 };
snprintf(heartbeat_buf, sizeof(heartbeat_buf), "HEARTBEAT_%d", heartbeat_count++);
ret = zmq_send(data_publisher, heartbeat_buf, strlen(heartbeat_buf) + 1, 0);
printf("[SENT HEARTBEAT] %s\n", heartbeat_buf);
sleep(2); // 每2秒发送一次
}
// 清理
printf("Shutting down client...\n");
g_running = false;
if (command_thread.joinable()) {
command_thread.join();
}
zmq_close(command_subscriber);
zmq_close(data_publisher);
zmq_ctx_destroy(context);
printf("Client exited successfully.\n");
return 0;
}
Cmake文件不变,然后make clean
make clean
cmake ..&&make
./zmp_client
Ctrl+C停止运行
如果启动上面线程就可以收到数据
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/zmp_client/build$ cmake ..&make
[1] 204384
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/Tronlong/mmcblk0p8/project_code/project/zmp_client/build
[ 25%] Building CXX object CMakeFiles/zmq_client.dir/src/main.cpp.o
[ 50%] Building CXX object CMakeFiles/zmq_client.dir/src/main1.cpp.o
[ 75%] Building CXX object CMakeFiles/zmq_client.dir/src/main2.cpp.o
[100%] Linking CXX executable zmq_client
[100%] Built target zmq_client
[1]+ Done cmake ..
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/zmp_client/build$ ./zmq_client
Starting ZMQ Client (Bidirectional)...
Client IP: 192.168.170.77
Connecting to server: 192.168.170.53
Port 5555: Receive commands from server
Port 5556: Send data to server
Command subscriber connected to tcp://192.168.170.53:5555
Waiting for connection stabilization...
Data publisher connected to tcp://192.168.170.53:5556
Client started successfully!
Starting data transmission...
Command receiver thread started
[RECV FROM SERVER] Command 30
[RECV FROM SERVER] Command 31
[SENT TO SERVER] SENSOR_DATA_0 from client
[SENT HEARTBEAT] HEARTBEAT_0
[RECV FROM SERVER] Command 32
[RECV FROM SERVER] Command 33
[SENT TO SERVER] SENSOR_DATA_1 from client
[SENT HEARTBEAT] HEARTBEAT_1
[RECV FROM SERVER] Command 34
[RECV FROM SERVER] Command 35
[SENT TO SERVER] SENSOR_DATA_2 from client
[SENT HEARTBEAT] HEARTBEAT_2
[RECV FROM SERVER] Command 36
[RECV FROM SERVER] Command 37
[SENT TO SERVER] SENSOR_DATA_3 from client
两者通过两个 设备互通,这种方式实现了一个完全对等的双向通信架构。
每个节点都是 “发布者 + 订阅者” 的组合体。
🔗 五、PAIR 模式(简洁双向)
PAIR 模式最接近传统的 Socket:
- 一对一绑定
- 全双工通信
- 适合同机内控制指令/状态交换
🧭 Host(主节点)
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "zmq.h"
#include <string>
#include <thread>
#include <atomic>
#include <iostream>
#include <chrono>
#include <conio.h>
std::atomic<bool> g_running{ true };
// 接收线程函数
void recv_thread(void* socket) {
printf("Receive thread started\n");
while (g_running) {
char buffer[1024] = { 0 };
int ret = zmq_recv(socket, buffer, sizeof(buffer) - 1, ZMQ_DONTWAIT);
if (ret > 0) {
printf("[RECV FROM CLIENT] %s\n", buffer);
// 根据接收到的消息类型进行响应
if (strstr(buffer, "SENSOR") != NULL) {
// 收到传感器数据,发送确认
const char* ack = "ACK_SENSOR_DATA";
zmq_send(socket, ack, strlen(ack) + 1, 0);
printf("[SENT TO CLIENT] %s\n", ack);
}
else if (strstr(buffer, "HEARTBEAT") != NULL) {
// 收到心跳,发送响应
const char* response = "HEARTBEAT_ACK";
zmq_send(socket, response, strlen(response) + 1, 0);
printf("[SENT TO CLIENT] %s\n", response);
}
}
else if (ret == -1 && zmq_errno() != EAGAIN) {
// 真正的错误
printf("Receive error: %s\n", zmq_strerror(zmq_errno()));
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
printf("Receive thread stopped\n");
}
int main() {
printf("Starting ZMQ PAIR Server...\n");
printf("Server IP: 192.168.170.53\n");
printf("Port 5555: PAIR communication with client\n");
void* context = zmq_ctx_new();
assert(context != NULL);
// 创建 PAIR socket
void* socket = zmq_socket(context, ZMQ_PAIR);
assert(socket != NULL);
int ret = zmq_bind(socket, "tcp://*:5555");
assert(ret == 0);
printf("PAIR socket bound to tcp://*:5555\n");
printf("Waiting for client connection...\n");
// 启动接收线程
std::thread t(recv_thread, socket);
// 主循环 - 发送命令和数据
int command_count = 0;
int data_count = 0;
printf("\nServer ready! Press:\n");
printf(" 'C' - Send command\n");
printf(" 'D' - Send data\n");
printf(" 'Q' - Quit\n");
while (g_running) {
if (_kbhit()) {
char key = _getch();
if (key == 'q' || key == 'Q') {
g_running = false;
break;
}
else if (key == 'c' || key == 'C') {
// 发送命令
char command[256];
snprintf(command, sizeof(command), "COMMAND_%d", command_count++);
ret = zmq_send(socket, command, strlen(command) + 1, 0);
printf("[SENT COMMAND] %s\n", command);
}
else if (key == 'd' || key == 'D') {
// 发送数据
char data[256];
snprintf(data, sizeof(data), "DATA_%d", data_count++);
ret = zmq_send(socket, data, strlen(data) + 1, 0);
printf("[SENT DATA] %s\n", data);
}
}
// 定期发送状态信息
static auto last_status_time = std::chrono::steady_clock::now();
auto now = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - last_status_time);
if (elapsed.count() >= 5) {
char status[256];
snprintf(status, sizeof(status), "STATUS: Server running, commands: %d, data: %d",
command_count, data_count);
ret = zmq_send(socket, status, strlen(status) + 1, 0);
printf("[SENT STATUS] %s\n", status);
last_status_time = now;
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
// 清理
printf("Shutting down server...\n");
g_running = false;
if (t.joinable()) {
t.join();
}
// 发送关闭消息
const char* shutdown_msg = "SERVER_SHUTDOWN";
zmq_send(socket, shutdown_msg, strlen(shutdown_msg) + 1, 0);
zmq_close(socket);
zmq_ctx_destroy(context);
printf("Server exited successfully.\n");
return 0;
}
如果启动下面线程就可以收到数据

Starting ZMQ PAIR Server...
Server IP: 192.168.170.53
Port 5555: PAIR communication with client
PAIR socket bound to tcp://*:5555
Waiting for client connection...
Server ready! Press:
'C' - Send command
'D' - Send data
'Q' - Quit
Receive thread started
[SENT STATUS] STATUS: Server running, commands: 0, data: 0
[RECV FROM CLIENT] SENSOR_DATA_0: temp=33.30, hum=58.60
[SENT TO CLIENT] ACK_SENSOR_DATA
[RECV FROM CLIENT] HEARTBEAT_0
[SENT TO CLIENT] HEARTBEAT_ACK
[SENT STATUS] STATUS: Server running, commands: 0, data: 0
[RECV FROM CLIENT] SENSOR_DATA_1: temp=32.70, hum=51.50
[SENT TO CLIENT] ACK_SENSOR_DATA
[RECV FROM CLIENT] HEARTBEAT_1
[SENT TO CLIENT] HEARTBEAT_ACK
[RECV FROM CLIENT] SENSOR_DATA_2: temp=34.30, hum=53.50
[SENT TO CLIENT] ACK_SENSOR_DATA
[RECV FROM CLIENT] HEARTBEAT_2
⚓ Device(从节点)
#include <iostream>
#include <thread>
#include <cstdio>
#include <vector>
#include <cstring>
#include <ctime>
#include <atomic>
#include <csignal>
#include <cmath>
#include "zmq.hpp"
// 定义结构体
struct SensorData
{
uint32_t sensor_id;
float value;
uint64_t timestamp;
};
struct ControlCommand
{
uint32_t device_id;
uint8_t command;
uint32_t parameter;
};
// 退出标志
std::atomic<bool> running{true};
// 信号处理函数
void signal_handler(int signum)
{
std::cout << "\nReceived signal " << signum << ", stopping..." << std::endl;
running = false;
}
// 序列化函数模板
template <typename T>
std::vector<uint8_t> serialize_struct(const T &data)
{
std::vector<uint8_t> buffer(sizeof(T));
std::memcpy(buffer.data(), &data, sizeof(T));
return buffer;
}
// 反序列化函数模板
template <typename T>
T deserialize_struct(const zmq::message_t &message)
{
T data{};
if (message.size() == sizeof(T))
{
std::memcpy(&data, message.data(), sizeof(T));
}
return data;
}
// 格式化时间戳
std::string format_timestamp(uint64_t timestamp)
{
time_t t = static_cast<time_t>(timestamp);
char buffer[20];
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", localtime(&t));
return std::string(buffer);
}
int main()
{
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
// 使用 PAIR 模式
const auto socket_path = "/mnt/project/zmp_message/.pair_socket";
zmq::context_t ctx(1);
zmq::socket_t pair_socket(ctx, zmq::socket_type::pair);
pair_socket.connect(std::string("ipc://") + socket_path);
// 设置接收超时
pair_socket.set(zmq::sockopt::rcvtimeo, 1000);
std::cout << "Device PAIR started. Sending sensor data and receiving commands..." << std::endl;
// 启动接收线程
std::thread receiver([&]()
{
while (true) {
if (!running) {
break;
}
try {
zmq::message_t message;
auto result = pair_socket.recv(message);
if (result) {
// 判断消息类型
if (message.size() == sizeof(ControlCommand)) {
ControlCommand command = deserialize_struct<ControlCommand>(message);
std::cout << "[RECV COMMAND] Device ID: " << command.device_id
<< ", Command: " << static_cast<int>(command.command)
<< ", Parameter: " << command.parameter << std::endl;
// 处理接收到的命令
switch(command.command) {
case 0:
std::cout << " -> Executing START command" << std::endl;
break;
case 1:
std::cout << " -> Executing STOP command" << std::endl;
break;
default:
std::cout << " -> Executing UNKNOWN command" << std::endl;
break;
}
} else {
std::cout << "[RECV UNKNOWN] Size: " << message.size() << std::endl;
}
}
} catch (const zmq::error_t& e) {
if (running && e.num() != EAGAIN) {
std::cerr << "Receive error: " << e.what() << std::endl;
}
break;
}
}
std::cout << "Receiver thread exiting." << std::endl; });
// 主循环发送传感器数据
int count = 0;
while (true)
{
if (!running) {
break;
}
try
{
// 发送传感器数据
SensorData sensor{
static_cast<uint32_t>(count % 5),
static_cast<float>(20.0 + 10.0 * sin(count * 0.5)), // 模拟传感器值
static_cast<uint64_t>(std::time(nullptr))
};
auto sensor_data = serialize_struct(sensor);
pair_socket.send(zmq::buffer(sensor_data), zmq::send_flags::none);
std::cout << "[SENT SENSOR] ID: " << sensor.sensor_id
<< ", Value: " << sensor.value
<< ", Time: " << format_timestamp(sensor.timestamp) << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
count++;
}
catch (const std::exception &e)
{
if (running) {
std::cerr << "Send error: " << e.what() << std::endl;
}
}
}
// 清理资源
running = false;
if (receiver.joinable())
{
receiver.join();
}
std::cout << "Device PAIR exited." << std::endl;
return 0;
}
Cmake文件不变,然后make clean
make clean
cmake ..&&make
./zmp_client
Ctrl+C停止运行
如果启动下面线程就可以收到数据
Tronlong@RK3576-Tronlong:~/mmcblk0p8/project_code/project/zmp_client/build$ ./zmq_client
Starting ZMQ PAIR Client...
Client IP: 192.168.170.77
Connecting to server: 192.168.170.53:5555
PAIR socket connected to tcp://192.168.170.53:5555
Client started successfully!
Starting data transmission...
Receive thread started
[SENT SENSOR] SENSOR_DATA_0: temp=33.30, hum=58.60
[SENT HEARTBEAT] HEARTBEAT_0
[RECV FROM SERVER] STATUS: Server running, commands: 0, data: 0
-> Server status update
[RECV FROM SERVER] ACK_SENSOR_DATA
-> Processing data...
[RECV FROM SERVER] HEARTBEAT_ACK
-> Received acknowledgment
[RECV FROM SERVER] STATUS: Server running, commands: 0, data: 0
-> Server status update
[SENT SENSOR] SENSOR_DATA_1: temp=32.70, hum=51.50
[SENT HEARTBEAT] HEARTBEAT_1
[RECV FROM SERVER] ACK_SENSOR_DATA
-> Processing data...
[RECV FROM SERVER] HEARTBEAT_ACK
-> Received acknowledgment
[SENT SENSOR] SENSOR_DATA_2: temp=34.30, hum=53.50
[SENT HEARTBEAT] HEARTBEAT_2
这样可以通过 Ctrl+C 优雅退出,线程安全且无资源泄露。
这个支持断电重连,very nice😘😘😘
🧩 七、三种模式对比
| 模式类型 | 通信方向 | 特点 | 适用场景 |
|---|---|---|---|
| PUB/SUB | 单向 | 广播式,一对多 | 数据分发(日志、传感器) |
| 双向 PUB/SUB | 双向 | 灵活扩展,可多节点 | 主从控制、任务指令 |
| PAIR | 双向 | 一对一、简洁高效 | 控制与状态同步 |
🧱 八、总结
本文展示了 ZeroMQ 在同一设备上的三种通信实现方式:
- 发布-订阅(PUB/SUB) —— 一对多信息分发
- 双向发布订阅(双节点互发) —— 双向协同通信
- 配对模式(PAIR) —— 简单高效的点对点交换
ZeroMQ 的设计使得这些模式都可以通过极少的代码完成,
并且支持无锁、异步、跨语言,非常适合在:
- 🛥️ 无人船控制
- 🤖 智能机器人
- 🧩 模块化仿真系统
等多进程通信场景中使用。
🧾 九、附录:参考文档
- 📘 ZeroMQ 官方指南 (zguide)
- 🌍 ZeroMQ 中文教程 (w3ccoo)
- 📚 ZeroMQ C++ API Reference
- 🧩 ZeroMQ GitHub Repo
- 🎶ZeroMQ“发布/订阅”模型的C++代码
💡 提示:在 Linux 环境下运行 IPC 套接字时,请确保路径存在,并拥有读写权限。
若在 Windows 使用,请将下位机Ubuntu中下位机代码改为"tcp://192.168.170.53:5555"为自己的地址,TCP 模式。
更多推荐


所有评论(0)