ZeroMQ
Brokerless messaging patterns — sockets that speak pub/sub, request/reply and push/pull.
What it is
ZeroMQ is a high-performance asynchronous messaging library for building distributed and concurrent applications. It provides sockets that carry atomic messages across processes, machines, or threads with patterns like pub-sub, request-reply, and pipeline.
ZeroMQ provides socket types (`REQ`, `REP`, `PUB`, `SUB`, `PUSH`, `PULL`) that can be connected in messaging topologies. It supports asynchronous, non-blocking communication, high throughput, and minimal latency.
- Licence
- MPL 2.0
- Watch for
- Messages are held in memory — a crash loses anything in flight
When to use it
The question documentation cannot answer for you — because it cannot recommend something else.
Reach for it when
- You want messaging patterns without operating a broker
- Low-latency inter-process or inter-thread communication
Look elsewhere when
- You need message durability, replay or delivery guarantees — that requires a real broker
- The team expects a managed queue with an operations dashboard
Installation
sudo apt install libzmq3-devGetting started
The smallest useful thing you can do with it, and what each part means.
#include <zmq.hpp>
#include <string>
#include <iostream>
int main() {
zmq::context_t context(1);
zmq::socket_t socket(context, ZMQ_REP);
socket.bind("tcp://*:5555");
while (true) {
zmq::message_t request;
socket.recv(request);
std::cout << "Received: " << request.to_string() << std::endl;
zmq::message_t reply("World", 5);
socket.send(reply, zmq::send_flags::none);
}
return 0;
}zmq::context_t context(1);
zmq::socket_t socket(context, ZMQ_REQ);
socket.connect("tcp://localhost:5555");
zmq::message_t request("Hello", 5);
socket.send(request, zmq::send_flags::none);
zmq::message_t reply;
socket.recv(reply);
std::cout << "Received reply: " << reply.to_string() << std::endl;Advanced usage
Where the library earns its place over a simpler alternative.
// Publisher
zmq::socket_t pub(context, ZMQ_PUB);
pub.bind("tcp://*:5556");
zmq::message_t msg("Update 1", 8);
pub.send(msg, zmq::send_flags::none);
// Subscriber
zmq::socket_t sub(context, ZMQ_SUB);
sub.connect("tcp://localhost:5556");
sub.set(zmq::sockopt::subscribe, "");zmq::socket_t push(context, ZMQ_PUSH);
push.bind("tcp://*:5557");
zmq::socket_t pull(context, ZMQ_PULL);
pull.connect("tcp://localhost:5557");zmq::message_t msg;
bool received = socket.recv(msg, zmq::recv_flags::dontwait);
if (received) {
std::cout << "Got message: " << msg.to_string() << std::endl;
}zmq::pollitem_t items[] = {{socket1, 0, ZMQ_POLLIN, 0}, {socket2, 0, ZMQ_POLLIN, 0}};
zmq::poll(items, 2, 1000);Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- zmq::error_t: Connection refused
- Ensure the server socket is bound and listening before connecting clients.
- zmq::error_t: Operation would block
- Occurs with non-blocking sockets. Check readiness with polling before sending/receiving.
- Dropped messages in PUB-SUB
- Subscribers only receive messages after they have subscribed. Consider buffering or queueing if needed.
Best practices
- Choose the right messaging pattern (`REQ-REP`, `PUB-SUB`, `PUSH-PULL`) for your use case.
- Use non-blocking sockets or polling to avoid deadlocks.
- Always close sockets and terminate the context to free resources.
- Handle network errors gracefully; ZeroMQ does not guarantee message delivery by default.
- For secure messaging, combine with encryption frameworks like CurveZMQ.
Alternatives
Comparable options, and the reason you would pick one over the other.
Background
Why it exists, and what it was reacting to.
ZeroMQ (also known as ØMQ) was created in 2007 by iMatix Corporation to provide a lightweight messaging layer that is faster and more flexible than traditional message brokers like AMQP or JMS. Unlike typical brokers, ZeroMQ is brokerless—applications communicate directly via sockets while still supporting rich messaging patterns. It has become popular in finance, IoT, distributed systems, and high-performance computing.
