Plugin Documentation

RealtimeIO
Socket.IO realtime client for Unreal

A Socket.IO client (events, namespaces, acknowledgements, binary payloads) with a Blueprint component and a full JSON value API.

v1.0.0
UE 4.27, 5.7 and 5.8
Win64 · Mac · Linux
Category Networking
Blueprints & C++
Alpha XP
RealtimeIO diagram
RealtimeIO — architecture & feature overview

Overview

RealtimeIO connects Unreal Engine to any Socket.IO server. It emits and receives named events with JSON or binary payloads, supports namespaces and server acknowledgements, reconnects automatically, and exposes everything through an actor component that works identically from Blueprints and C++.

Typical uses: game/session chat, live dashboards and telemetry, matchmaking lobbies, IoT bridges, companion apps, and any gameplay that must react to server pushes without polling.

What's in the box Five modules — RealtimeIO (component + Blueprint layer), RealtimeIOJson (Blueprint JSON types), RealtimeIOLib (the underlying Socket.IO protocol implementation), RealtimeIOCore (threading & utility helpers) and RealtimeIOEditor (editor nodes such as Break Json). Full C++ source is included.

Requirements

RequirementDetails
Unreal Engine4.27, 5.7 and 5.8
PlatformsWin64 · Mac · Linux
LanguageBlueprints and/or C++ — no C++ required for any feature
ServerAny Socket.IO-compatible server (Node.js reference implementation, python-socketio, netty-socketio, …). A server is not included — see Setting up a server.
Bundled librariesasio, websocketpp, rapidjson ship inside Source/ThirdParty and are compiled into the plugin. Nothing to download or install.

Installation

From Fab

  1. Install the plugin to your engine through the Epic Games Launcher (Library → Fab Library → Install to Engine).
  2. Open your project, then open Edit → Plugins, search for RealtimeIO and make sure it is enabled. Restart the editor if prompted.

Manual (per-project) install

  1. Copy the RealtimeIO folder into your project's Plugins/ directory (create the directory if it doesn't exist).
  2. C++ projects: right-click the .uprojectGenerate project files, then build. Blueprint-only projects can launch the editor directly — the editor compiles the plugin on first load.
  3. Confirm the plugin is listed and enabled under Edit → Plugins → Networking.
Verify it works Add a component to any actor (Add Component button) and type “RealtimeIO”. If the component appears, the plugin is installed and ready.

Setting up a server

RealtimeIO is a client. To try it you need a Socket.IO server to connect to — the plugin talks to any Socket.IO-compatible implementation you may already run in production. If you don't have one yet, the reference Node.js server takes two minutes:

  1. Install Node.js (LTS) from nodejs.org — the installer includes npm.
  2. Create an empty folder, open a terminal in it and run:
    npm init -y
    npm install socket.io
  3. Save the following as server.js:
    const { Server } = require("socket.io");
    const io = new Server(3000);
    
    io.on("connection", (socket) => {
      console.log("client connected:", socket.id);
    
      // echo any "chat message" event back to every client
      socket.on("chat message", (msg) => {
        console.log("received:", msg);
        io.emit("chat message", msg);
      });
    
      // acknowledgement example (see the Acknowledgements section)
      socket.on("ping me", (data, ack) => {
        if (ack) ack({ pong: Date.now() });
      });
    
      socket.on("disconnect", () => console.log("client left:", socket.id));
    });
    
    console.log("Socket.IO server listening on http://localhost:3000");
  4. Run it: node server.js

Your server is now reachable at http://localhost:3000 — the plugin's default address. For other languages and production topics (rooms, scaling, TLS termination) see the official guides at socket.io/docs.

Quick start — Blueprints

Goal: connect, receive chat message events, and send one. No C++ involved.

  1. Open (or create) an actor Blueprint and click Add Component → RealtimeIO.
  2. Select the component. In Details → RealtimeIO Connection Properties you'll find URL Params → Address And Port, preset to http://localhost:3000. Change it to your server if needed.
  3. Should Auto Connect is on by default, so the component connects on Begin Play. (Untick it if you prefer to call Connect yourself.)
  4. With the component selected, add the On Connected event from the Details panel's Events section. It fires with your Socket Id and Session Id once the handshake completes.
  5. Receive events: call Bind Event To Generic Event (Event Name = chat message) — e.g. right after On Connected — then add the component's On Generic Event event. Every bound event arrives there with its Event Name and an Event Data (RealtimeIO Json Value) pin. Drag off Event Data and use To String (JsonValue) to print it.
  6. Send events: call Emit (Event Name = chat message). The Message pin accepts a plain String, Integer, Float or Bool directly — Blueprint auto-casts them via the To JsonValue conversion nodes. For structured payloads see Working with JSON.
Route different events to different functions Instead of the generic event you can call Bind Event To Function (Event Name, Function Name, Target). The named function must be a custom event/function on the target with a single RealtimeIO Json Value input — it will be called directly whenever that event arrives.
Connection lifetime By default the connection lives with the component (ends on End Play). Enable Plugin Scoped Connection on the component to keep one shared connection alive across level travel — components with the same Plugin Scoped Id reuse it, and your bound events survive the transition.

Quick start — C++

Add the modules to your <Game>.Build.cs:

PrivateDependencyModuleNames.AddRange(new string[] {
    "RealtimeIO", "RealtimeIOJson", "Json"
});

Minimal actor that connects, listens and emits:

#include "RealtimeIOComponent.h"

AMyActor::AMyActor()
{
    Socket = CreateDefaultSubobject<URealtimeIOComponent>(TEXT("RealtimeIO"));
}

void AMyActor::BeginPlay()
{
    Super::BeginPlay();

    // bind before (or after) connecting - both work
    Socket->OnNativeEvent(TEXT("chat message"),
        [](const FString& Event, const TSharedPtr<FJsonValue>& Payload)
        {
            UE_LOG(LogTemp, Log, TEXT("%s: %s"), *Event, *Payload->AsString());
        });

    Socket->Connect(TEXT("http://localhost:3000"));
}

void AMyActor::SendHello()
{
    Socket->EmitNative(TEXT("chat message"), FString(TEXT("Hello from Unreal!")));
}

EmitNative is overloaded for FString, numbers, bool, TArray<uint8> (binary), TSharedPtr<FJsonObject>, TSharedPtr<FJsonValue>, arrays of values, and even raw UStruct* pointers (auto-converted to JSON). Every overload takes an optional callback receiving the server's acknowledgement:

Socket->EmitNative(TEXT("ping me"), FString(),
    [](const TArray<TSharedPtr<FJsonValue>>& Response)
    {
        // Response holds the arguments the server passed to ack(...)
    });
Threading Callbacks are delivered on the game thread by default, so it is safe to touch actors and UI from them. OnNativeEvent takes an optional thread-override parameter if you want networking-thread delivery instead.

Component reference

Everything below lives on URealtimeIOComponent (Blueprint category “RealtimeIO”).

Functions

NodeTypeDescription
ConnectCallableConnect to Address And Port (e.g. http://localhost:3000) with optional path (default socket.io), auth token, query and headers.
Connect With ParamsCallableConnect using a RealtimeIO Connect Params struct (address, path, auth token, extra auth pairs, query map, header map).
DisconnectCallableClose the connection (async).
EmitCallableSend an event with an optional RealtimeIO Json Value payload to a namespace (default /).
Emit With Call BackCallableEmit and route the server's acknowledgement to a named function on a target object.
Emit With Graph Call BackCallableLatent version — the node's Result pin fires when the acknowledgement arrives; the result value is the server's reply.
Bind Event To Generic EventCallableSubscribe an event name; occurrences arrive on the component's On Generic Event.
Bind Event To FunctionCallableSubscribe an event name and call the named function (one RealtimeIO Json Value parameter) on the target object when it fires.
Bind Event To DelegateCallableSubscribe an event name to a custom Blueprint delegate.
Unbind EventCallableStop listening to an event name.
Join Namespace / Leave NamespaceCallableExplicitly join or leave a socket.io namespace (joining is automatic when you bind/emit to one).

Events

EventPayload pinsFires
On ConnectedSocket Id, Session Id, Is ReconnectionHandshake complete; connection is usable.
On DisconnectedClose ReasonConnection closed (by either side).
On Connection ProblemsAttempts, Next Attempt In Ms, Time Since ConnectedConnection lost/unreachable; automatic retries are running.
On Generic EventEvent Name, Event Data (Json Value)Any event bound via Bind Event To Generic Event arrives.
On Socket Namespace Connected / DisconnectedNamespaceJoined / left a namespace.
On FailConnection attempt failed.
On ErrorError TextThe server sent a socket.io error packet.

Key properties

PropertyTypeDescription
URL ParamsConfigDefault connection settings used on auto-connect: Address And Port, Path (socket.io), Auth Token, Extra Auth, Query map, Headers map.
Should Auto ConnectConfigConnect on Begin Play (default: on).
Reconnection Delay In Ms / Max Reconnection Attempts / Reconnection TimeoutConfigRetry pacing. Defaults retry forever — cap attempts or timeout for fail-fast behaviour.
Force TLSConfigUse TLS even for plain http:// URLs.
Should Verify TLS CertificateConfigLeave off: certificate verification is not implemented in the bundled TLS layer; enabling it will fail the handshake. Terminate TLS at a proxy if you need verified certs.
Plugin Scoped Connection / Plugin Scoped IdConfigKeep one shared connection alive across levels; components sharing an Id share the socket and its bindings.
Unbind Events On DisconnectConfigAuto-clean bindings when the connection closes.
Verbose Connection LogConfigExtra log output for connection diagnostics.
Is Connected / Socket Id / Session Id / Is Having Connection ProblemsRead-onlyLive connection state.

Working with JSON

Payloads travel as RealtimeIO Json Value / RealtimeIO Json Object objects (module RealtimeIOJson).

Building a payload

  1. Simple values: plug a String / Integer / Float / Bool straight into Emit — the To JsonValue autocast nodes convert them implicitly. Byte arrays convert the same way for binary.
  2. Objects: create a RealtimeIO Json Object (Construct node), fill it with its Set String/Number/Bool/Array/Object Field nodes, then plug it into Emit (autocasts via To JsonValue (JsonObject)).
  3. Whole structs: To JsonValue (Struct) / Struct To Json Object serialize any Blueprint struct in one node — ideal for sending gameplay state. Json Object To Struct does the reverse on receive.

Reading a payload

  1. Drag off Event Data and use To String / To Integer / To Float / To Bool / To Bytes (JsonValue) for simple values.
  2. For objects: To Object (JsonValue), then Get … Field nodes — or the editor's Break Json node, which exposes chosen fields as typed output pins.
  3. Files: Save Struct To Json File / Load Json File To Struct persist structs to disk as JSON.

Base64 helpers (Base64 Encode / Decode, string and bytes variants) and Percent Encode are included for interop with web APIs.

Acknowledgements (request/response)

Socket.IO lets the server answer a specific emit. Three ways to consume the reply:

NodeStyleUse when
Emit With Graph Call BackLatent pinBlueprint request/response in a single node — execution resumes on the Result pin with the server's reply.
Emit With Call BackNamed functionYou want the reply delivered to a specific function (one RealtimeIO Json Value parameter).
EmitNative(..., Callback)C++ lambdaNative code — the lambda receives all ack arguments as TArray<TSharedPtr<FJsonValue>>.

Server side, an acknowledgement is just the callback parameter: socket.on("ping me", (data, ack) => ack({ pong: Date.now() })) — see the server example.

Namespaces

Namespaces multiplex one physical connection into separate channels (/, /chat, /admin, …). Every Emit and Bind node has a Namespace pin (default /). Binding or emitting to a namespace joins it automatically; Join Namespace / Leave Namespace give you explicit control, and On Socket Namespace Connected / Disconnected report membership changes. Normalize Namespace (utility) ensures a name is /-prefixed.

Binary data

Socket.IO supports raw binary alongside JSON. In Blueprints, plug a Byte array into Emit (autocast To JsonValue (Bytes)) and read incoming binary with To Bytes (JsonValue). In C++ use the TArray<uint8> overload of EmitNative; incoming binary values arrive as FJsonValueBinary. Useful for screenshots, audio chunks, or compact custom protocols.

Utility node pack

General-purpose networking utilities added to URealtimeIOFunctionLibrary — available from Blueprints and C++.

NodeTypeDescription
Construct RealtimeIO ComponentCallableCreate a RealtimeIO component at runtime on any actor.
Is Secure RealtimeIO Url / Is Valid RealtimeIO UrlPureURL scheme / shape checks before connecting.
Normalize NamespacePureEnsure a namespace begins with /.
CRC32 Of BytesPureCRC32 checksum of a byte array.
MD5 Of String / SHA1 Of StringPureHex digests of a UTF-8 string.
Make Guid StringPureNew random GUID (hyphenated).
Now Unix SecondsPureCurrent UTC time as Unix seconds.
Unix Seconds To ISO8601PureUnix seconds → ISO-8601 UTC string.
Format Byte SizePureHuman-readable size, e.g. 1536 → 1.5 KB.
Random TokenPureRandom alphanumeric token (ids, nonces).
XOR Bytes With KeyPureXOR bytes with a repeating key (obfuscation, not encryption).
Is Valid HostnamePureRFC-952/1123-style hostname validation.

Troubleshooting

SymptomFix
Never connects / On Connection Problems loopsConfirm the server is running and reachable (http://host:port, not ws://), the port matches, and a firewall isn't blocking it. Enable Verbose Connection Log and check the Output Log.
Connects but events never arriveEvent names are case-sensitive and must match the server exactly. Check the Namespace pin — an event bound on / won't receive emissions on /chat. Verify the binding ran (it can be done before or after connecting).
TLS (https://) connection failsSet Should Verify TLS Certificate to false (verification is not implemented — it always fails when enabled). For verified certificates, terminate TLS at a reverse proxy (nginx/caddy) in front of your server.
Custom path server (e.g. behind a proxy)Set the Path field in URL Params — default is socket.io, matching the reference server's default mount point.
Auth-protected server rejects the handshakeFill Auth Token (sent as auth: { token }) and/or Extra Auth / Query / Headers maps in URL Params to match what your middleware expects.
Old Socket.IO 2.x server won't accept the clientEnable allowEIO3: true on a v4 Node server, or upgrade the server — see socket.io migration notes.
Connection drops on level changeExpected with a component-scoped connection. Enable Plugin Scoped Connection to persist the socket across travel.
Packaged build can't connect (editor works)Make sure the plugin is enabled in the project (not only the editor session) and the target platform is Win64, Mac or Linux. For shipping builds double-check your server address isn't a dev-only localhost.

Extending the plugin

Full source ships in the package — you can read, debug and modify every layer:

ModuleLocationWhat to change there
RealtimeIOSource/RealtimeIOThe component and Blueprint surface (RealtimeIOComponent.h), the native client wrapper (RealtimeIONative.h) and the function library. Add new nodes or connection behaviours here.
RealtimeIOJsonSource/RealtimeIOJsonBlueprint JSON types, struct⇄JSON conversion, Base64 helpers.
RealtimeIOLibSource/RealtimeIOLibThe Socket.IO protocol engine (sio_client/sio_socket) over the vendored asio + websocketpp stack. Protocol-level changes go here.
RealtimeIOCoreSource/RealtimeIOCoreThreading helpers (lambda runnables), file subsystem and misc utilities shared by the other modules.
RealtimeIOEditorSource/RealtimeIOEditorEditor-only K2 nodes (Break Json).

To iterate on the plugin itself, install it into a C++ project's Plugins/ folder (see manual install) so your IDE rebuilds it with the project. C++ types are exported (REALTIMEIO_API), so game modules can subclass the component or call RealtimeIONative directly.

Credits & third-party

© Alpha XPalphaxp.net. Developed and maintained for UE 4.27, 5.7 and 5.8.

The plugin bundles the header-only libraries asio, websocketpp and rapidjson (in Source/ThirdParty, compiled into the plugin — no separate installation required). Their license texts are included in the package. The Socket.IO server is separate software installed by you (see Setting up a server) under its own license (MIT for the Node.js reference implementation).