# Basic Pub/Sub (/sdks/cpp/tutorials/basic-pubsub)



## Overview [#overview]

This tutorial builds the "hello world" of KubeMQ messaging: a publisher and a subscriber talking over the **Events** pattern. Events are fire-and-forget — the broker fans a message out to every subscriber currently listening on the channel and moves on. There's no persistence, no acknowledgment, and no replay, which makes this the pattern to reach for when you need low-latency, high-throughput broadcast (metrics ticks, live status updates, cache-invalidation signals) and can tolerate losing a message if nobody is listening at the moment it's sent.

You'll wire up `SubscribeToEvents()` with callback lambdas, give the subscription a moment to register with the server, then build an event with `Event::Builder()` and publish it with `SendEvent()`. The empty consumer-group argument means fan-out delivery: every connected subscriber gets its own copy, as opposed to a consumer group where only one member would receive it. &#x2A;*Gotchas:** if the subscriber isn't fully established before you publish, the event is simply gone — there's no queue catching it, which is why the sample sleeps briefly before sending; and because delivery isn't acknowledged, a crashed or disconnected subscriber never knows it missed anything.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* C++ SDK installed (vcpkg or CMake FetchContent)
* C++17 compiler (GCC 9+, Clang 9+, MSVC 2019+)

## Code [#code]

```cpp title="main.cc"
// Example: events/basic_pubsub
//
// Demonstrates basic fire-and-forget event publish/subscribe.
// A subscriber listens on a channel, then a publisher sends an event.
//
// Channel: cpp-events.basic-pubsub
// Client ID: cpp-events-basic-pubsub-client
//
// Run with a KubeMQ server on localhost:50000
// (see https://docs.kubemq.io/deploy).

#include <kubemq/kubemq.h>

#include <chrono>
#include <iostream>
#include <thread>

int main() {
    std::cout << "[1] Connecting to localhost:50000" << std::endl;

    kubemq::ClientOptions options;
    options.set_address("localhost", 50000);
    options.set_client_id("cpp-events-basic-pubsub-client");

    auto client_result = kubemq::Client::Create(options);
    if (!client_result.ok()) {
        std::cerr << "[ERROR] Failed to create client: " << client_result.status().message()
                  << std::endl;
        return 1;
    }
    auto& client = *client_result;

    std::string channel = "cpp-events.basic-pubsub";

    // Subscribe to events on the channel.
    std::cout << "[2] Subscribing to channel " << channel << std::endl;
    auto sub_result = client->SubscribeToEvents(
        channel, "",
        [](const kubemq::EventReceive& event) {
            std::cout << "[4] Received: channel=" << event.channel << " body=" << event.body
                      << " metadata=" << event.metadata << std::endl;
        },
        [](const kubemq::Status& err) {
            std::cerr << "[ERROR] Subscription error: " << err.message() << std::endl;
        });
    if (!sub_result.ok()) {
        std::cerr << "[ERROR] SubscribeToEvents: " << sub_result.status().message() << std::endl;
        return 1;
    }
    auto& sub = *sub_result;

    // Allow subscription to fully establish before publishing.
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // Publish an event to the channel.
    auto event_result = kubemq::Event::Builder()
                            .SetChannel(channel)
                            .SetBody("hello from C++ SDK")
                            .SetMetadata("greeting")
                            .Build();
    if (!event_result.ok()) {
        std::cerr << "[ERROR] Build event: " << event_result.status().message() << std::endl;
        return 1;
    }
    auto send_status = client->SendEvent(*event_result);
    if (!send_status.ok()) {
        std::cerr << "[ERROR] SendEvent: " << send_status.message() << std::endl;
        return 1;
    }
    std::cout << "[3] Event published" << std::endl;

    // Wait for the event to be received.
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::cout << "[5] Event received successfully" << std::endl;

    // Cancel the subscription explicitly.
    // Note: Subscription destructor would also handle cleanup (RAII)
    sub->Cancel();
    std::cout << "[6] Subscription cancelled" << std::endl;

    auto close_status = client->Close();
    if (!close_status.ok()) {
        std::cerr << "[ERROR] Close failed: " << close_status.message() << std::endl;
        return 1;
    }
    std::cout << "[7] Client closed" << std::endl;

    return 0;
}
```

## How It Works [#how-it-works]

* Subscribes to events on a channel using `SubscribeToEvents()` with callback lambdas.
* Builds an event using `Event::Builder()` with channel, body, and metadata.
* Sends the event with `SendEvent()` and waits for the subscriber to receive it.
* Cancels the subscription with `sub->Cancel()` and closes the client.

## Related [#related]

* [Pattern overview](/learn/events/getting-started)
* [C++ SDK Reference](/sdks/cpp/reference/events)
* [Consumer Group](/sdks/cpp/how-to/events/consumer-group)
* [Stream Send](/sdks/cpp/how-to/events/stream-send)
