This example demonstrates how to use NNG (Nanomsg Next Generation) with Unix Domain Sockets for inter-process communication using the PUB/SUB pattern.
The PUB/SUB pattern is ideal for:
- Event broadcasting: System events, status updates, notifications
- Log streaming: Centralized logging distribution
- Module communication: Inter-module event passing within the same machine
- Real-time monitoring: Status updates to multiple monitoring clients
- Unix Domain Socket (IPC): File-based communication (
ipc:///tmp/nng_pubsub) - Signal handling: Graceful shutdown with Ctrl+C
- Memory management: Proper cleanup of allocated buffers
- Error handling: Comprehensive error checking and reporting
nng-example/
├── pub_server.c # Publisher (server)
├── sub_client.c # Subscriber (client)
├── CMakeLists.txt # CMake build configuration
├── Makefile # Alternative Makefile build
└── README.md # This file
Ubuntu/Debian:
sudo apt-get update
sudo apt-get install -y libnng-devmacOS (with Homebrew):
brew install nngManual Installation:
git clone https://github.com/nanomsg/nng.git
cd nng
mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make install# Create build directory
mkdir build && cd build
# Configure and build
cmake ..
make
# Or build individually
make pub_server
make sub_client# Build both publisher and subscriber
make all
# Or build individually
make pub_server
make sub_client./pub_serverThe publisher will:
- Create a Unix Domain Socket at
/tmp/nng_pubsub - Start publishing messages every second
- Display published messages with timestamps
In separate terminal windows:
./sub_clientYou can run multiple subscribers simultaneously - they will all receive the same messages.
Press Ctrl+C in any terminal to gracefully shut down the application.
Publisher:
Publisher started on ipc:///tmp/nng_pubsub
Press Ctrl+C to stop...
PUB: tick 0 - timestamp: 1703123456
PUB: tick 1 - timestamp: 1703123457
PUB: tick 2 - timestamp: 1703123458
Subscriber:
Subscriber connected to ipc:///tmp/nng_pubsub
Waiting for messages... (Press Ctrl+C to stop)
SUB: tick 0 - timestamp: 1703123456
SUB: tick 1 - timestamp: 1703123457
SUB: tick 2 - timestamp: 1703123458
# From build directory
make help # Show all available targets
make run-pub # Run publisher
make run-sub # Run subscriber
make clean-socket # Remove socket file
make clean # Remove build artifactsmake help # Show all available commands
make clean # Remove build artifacts and socket file
make install-deps # Install NNG library (Ubuntu/Debian)
make install-deps-macos # Install NNG library (macOS)
make run-pub # Run publisher in background
make run-sub # Run subscriber
make stop # Stop all running processes-
File-based (
ipc:///tmp/nng_pubsub):- Creates a socket file at the specified path
- Requires proper file permissions
- Visible in filesystem
-
Abstract namespace (
ipc://@nng_pubsub):- Linux-specific feature
- No filesystem representation
- Automatically cleaned up on process exit
- Fire-and-forget: No delivery guarantees
- Fan-out: One publisher can serve multiple subscribers
- Topic filtering: Subscribers can filter by message prefixes
- Late joiners: New subscribers only receive messages published after they connect
The example includes comprehensive error handling for:
- Socket creation failures
- Connection errors
- Send/receive failures
- Signal handling for graceful shutdown
// Publisher sends system status
snprintf(msg, sizeof(msg), "CPU: %.1f%% MEM: %.1f%%", cpu_usage, mem_usage);
nng_send(pub, msg, strlen(msg) + 1, 0);// Publisher sends log events
snprintf(msg, sizeof(msg), "LOG: [%s] %s", level, message);
nng_send(pub, msg, strlen(msg) + 1, 0);// Publisher sends module events
snprintf(msg, sizeof(msg), "MODULE: %s STATUS: %s", module_name, status);
nng_send(pub, msg, strlen(msg) + 1, 0);# Check socket file permissions
ls -la /tmp/nng_pubsub
# Remove old socket file if needed
rm -f /tmp/nng_pubsub- Ensure publisher is running before starting subscribers
- Check if socket file exists and has proper permissions
- Verify no other process is using the same socket path
- Ensure NNG library is properly installed
- Check that development headers are available
- Verify compiler supports C99 standard
// Subscribe to specific topics
nng_setopt(sub, NNG_OPT_SUB_SUBSCRIBE, "ERROR", 5); // Only error messages
nng_setopt(sub, NNG_OPT_SUB_SUBSCRIBE, "WARN", 4); // Only warning messagesYou can extend this example to support multiple publishers by using different socket paths or implementing a more sophisticated routing mechanism.
This example is provided as-is for educational purposes. NNG is licensed under the MIT License.