ZLink Framework C++ — User Guide¶
View in another language — C++ · C#/.NET · Java · Kotlin · Node/TypeScript
A C++ application framework for building server systems where real-time messaging matters out of several cooperating processes.
#include <zlink/framework.hpp>
int main (int argc, char **argv)
{
auto app = zlink::framework::app_t::create ();
app.add_zlink_framework ([] (zlink::framework::zlink_framework_options_t &options) {
options.http ()
.listen ("http://0.0.0.0:8080")
.map_post<open_conversation_http_handler_t> ("/conversations");
});
return app.run (argc, argv);
}
Register one handler class and the framework handles message decoding, routing, and encoding.
Systems It Is Built For¶
It's designed for systems where several server processes split responsibilities and cooperate, and where a state change must reach the client in real time.
| Domain | Core scenario |
|---|---|
| Real-time games | Create room → player joins → game state updates → push to client |
| Customer support chat | Open conversation → assign agent → relay messages → push conversation state |
| Order workflow | Accept order → process in stages → change state → notify client |
| Delivery/dispatch | Request dispatch → assign/accept a driver → track state → push in real time |
There's one common shape — role-specific server processes talk in typed messages, and the client receives state changes over a real-time connection (stream).
Each server process is an independent executable connected to the others over TCP. HTTP
ingress, the communication path to other servers, client connections, and state-unit
management all live inside one server. samples/TicTacToe (2 servers) and samples/Bingo
(4 servers) are complete working examples.
Core Capabilities¶
Channel Messaging — typed request-reply between servers¶
A channel is a name given to a communication path between servers. One side sends a request
by channel name, and the other side processes it and replies. structs are exchanged
directly, and the framework handles serialization (JSON / MessagePack / Protobuf).
// Sending side (channel client)
auto result = co_await _client
.request ("support.core", open_conversation_req_t{user_id})
.async<open_conversation_res_t> ();
// Receiving side (channel server handler)
class open_conversation_handler_t {
public:
using request_type = open_conversation_req_t;
using reply_type = open_conversation_res_t;
static constexpr const char *topic_name = "OpenConversation";
open_conversation_res_t handle (const open_conversation_req_t &req) { ... }
};
Besides request-reply, it also provides fanout (pub/sub) and route mesh (address routing) patterns. Channel messaging →
SPOT — managing a state unit without locks¶
A SPOT is an execution unit that binds "one state region" — a game room, a support
conversation, an order-processing unit — together with its participants. Everything that
happens inside one SPOT — participant packets, timers, join/leave — is processed
serially. State can be accessed without std::mutex, and even with coroutine-based
async processing, two requests never overlap within the same SPOT.
class conversation_spot_t : public zlink::framework::spot_t,
public conversation_t // owns conversation state directly
{
public:
void configure (zlink::framework::spot_context_t &context)
{
context.handlers ().add_actor_packet<&conversation_spot_t::send_message> ();
}
send_message_res_t send_message (const user_actor_t &actor,
const zlink::framework::message_context_t &,
const send_message_req_t &request)
{
return append (actor.user_id, request.text); // safe without std::mutex
}
};
It splits into the entry spot (one per node), responsible for assignment/placement, and the room spot (one per unit), the state body itself. Periodic work is registered as a timer. Spot →
Stream + Actor — real-time client connections¶
A client's real-time bidirectional connection is called a stream, and the server-side object that represents one connection is an actor. When a client connects, the session creates an actor, and the actor joins a SPOT to participate in state processing.
class support_session_t : public zlink::framework::packet_stream_session_t {
public:
task_t<void> on_packet (stream_t &stream,
const stream_dispatch_context_t &dispatch,
const zlink::message_t &payload) override
{
auto actor = co_await _actors.find (actor_id);
co_await actor.value ().relay (payload); // forward the current dispatch's packet to the actor
}
};
The client-side connection is handled by a separate deliverable, the stream connector. Chapter 8 → · Chapter 9 →
HTTP Hosting — a REST API embedded inside the server process¶
Host REST endpoints in the same process without a separate web server. You can implement path parameters and authentication logic in middleware/handlers, TLS is supported, and readiness / liveness / health-check endpoints register in one line.
options.http ()
.listen ("https://0.0.0.0:8443")
.configure_tls ([] (auto &tls) {
tls.certificate_file (cert_path).private_key_file (key_path);
})
.map_post<create_game_http_handler_t> ("/games")
.map_get<get_room_http_handler_t> ("/rooms/{room_id}")
.map_readiness ("/ready");
Configuration · DI · Logging · Monitoring¶
Built-in support for what a production server needs.
- Configuration — composes CLI arguments, environment variables, and a JSON file in
priority order. One call to
bind<T>()maps a settings section onto a struct. - DI container — handler constructor parameters get services auto-injected. Supports singleton / scoped / transient lifetimes.
- Logging — inject a
logger_t<TOwner>via DI and get logs auto-tagged with the source name. - Monitoring / Health — receive socket, discovery, spot, and timer events as typed
subscriptions. Wire health checks to
/readyand/healthzendpoints.
Chapter 18 → · Chapter 19 → · 11. Monitoring chapter
Registry / Discovery — automatic server address wiring¶
When several Play server instances come up, you don't hardcode which server to connect to or
its endpoint. A shared Redis-backed Location Store tracks addresses, and each server discovers
them dynamically through add_location_store<redis::redis_location_store_t> ().
options.add_location_store<redis::redis_location_store_t> ()
.set_connection_string (topology.redis_endpoint)
.set_key_prefix (topology.redis_key_prefix + "location:");
auto room_mesh = options.add_route_mesh (sample_names_t::room_spot_mesh);
room_mesh.set_routing_id (zlink::routing_id_t::from ("bingo-play-" + topology.play_node))
.listen (topology.selected_play_spot_router_endpoint ());
room_mesh.objects ()
.server ()
.add_entry_spot<bingo_entry_spot_t> ()
.add_spot_factory<bingo_room_spot_t> (sample_names_t::room_spot);
Table Of Contents¶
| Order | Document | Content |
|---|---|---|
| 1 | Overview | A quick map of the core surface, layers, and topology |
| 2 | Interactive Tour | Step through how each feature behaves, using a single MORPG |
| 3 | Quickstart | Install, a minimal project where two processes call each other, first-run checks |
| 4 | Core Concepts | What a channel, a Spot, an Actor and a session each are |
| 5 | Channel Messaging | The path that calls by name — registering and calling |
| 6 | Spot | Creating and calling a shared place by id |
| 7 | Actor | Creating and calling one entity by id |
| 8 | STREAM | A client outside the mesh attaching over one connection |
| 9 | Session and Actor | Binding one connection to one Actor |
| 10 | Location | Looking up the node something is on by id |
| 11 | Monitoring | A placeholder in the feature guide — no body yet |
| 12 | The Execution Model | Two queues, the serialization scope, the turn |
| 13 | Backpressure | When arrival outruns processing, and the options that affect it |
| 14 | Activation and Lifetime | Creation time per kind, lifecycle callbacks, injection lifetime |
| 15 | Actor Membership | Moving between Spots, reservations and limits |
| 16 | Timers and Workers | Periodic execution, running outside the line, giving the turn back |
| 17 | Relocation | What survives a move, the adapter, the unit |
| 18 | How Channels Work | Pattern differences, target selection, pub/sub, connection and discovery |
| 19 | Handlers and Message Processing | Registration variants, filters, codecs, handler kinds |
| 20 | How STREAM Works | Startup checks, error ownership, reply tokens, execution mode |
| 21 | How Session Binding Works | How many bindings, route refresh, disconnect, failures |
| 22 | Operations and Lifecycle | Runtime metrics, relocate, drain, readiness wiring |
| 23 | Options | The option list, the defaults and when to change them |
| 24 | Picking a Sample | Choosing which sample to read first and how to run it |
| 25 | Reading Along: Bingo | Authentication, matching, rooms, timers, multicast and cleanup in code order |
| 26 | Reading Along: TicTacToe | Manual connection and registration, an Actor join onto another node |
| 27 | Reading Along: SupportChat | Several Actors on one session, metadata relay, the idle timer |
| 28 | Reading Along: DeliveryDispatch | One-way sends, deadline records and reassignment, customer pushes |
| 29 | Reading Along: ShoppingMall | The owner Instance Spot, replay, next step and expected version |
| 30 | Reading Along: GameQuest | A per-player owner, best-effort pushes and reconciliation |
| 31 | Reading Along: ZoneWorld | Capacity placement, boundary joins and relocation, fanout and observation |
| 32 | E2E Testing | Verifying the whole system with the client library |
| 33 | Key Type Index | The contract interfaces indexed by their verification code |
| 34 | DI Container | ZLink host — the three lifetimes, registration, handler injection |
| 35 | Configuration | ZLink host — sources, precedence, section binding |
| 36 | HTTP Hosting | ZLink host — the embedded HTTP server and route handlers |
| 37 | Execution and Configuration Model | ZLink host — where the thread model meets configuration |
| 38 | Monitoring | Awaiting rewrite — status snapshots and diagnostics |
The file number identifies the same chapter regardless of language. Chapters 1–17 are shared across all five languages, and chapters 18–21 are C++-only — DI, configuration, and HTTP hosting, which .NET gets from its runtime, are provided directly by the framework in C++, as is the execution model.
These four are foundational, so after reading chapters 2 and 3 you can jump straight to 18–21 and come back to chapter 4.
How To Read The Diagrams¶
Every diagram in this guide uses the same visual language — color maps to concept.
Several chapters draw the same TicTacToe/Bingo topology, and only the zoomed-in location changes per chapter.
Related Documents¶
- The HTTP client (the side that sends requests) is a separate deliverable — zlink::http_client user guide
- The design contract (draft) lives in doc/spec/. When it conflicts with the guide, the code and the spec are authoritative.