WuKongIM Docs

C# quickstart

Integrate the WuKongEasySDK-CSharp NuGet release with .NET 8 for authentication, online messaging, automatic reconnect, and async cleanup.

WuKongEasySDK-CSharp follows the JavaScript EasySDK WebSocket JSON-RPC protocol with idiomatic async C# APIs and typed events. It has no third-party runtime dependencies.

NuGet release 1.0.0

WuKongEasySDK 1.0.0 is published on nuget.org from source 02ea7d60cd94feef1996f41bca35ffc3b8e18ea6. The default installation below uses public NuGet; project references and local packing remain available for source builds.

Before you begin

  • Prepare .NET 8 or later on Windows, Linux, or macOS. The target framework is net8.0; Unity, .NET Framework, and browser WebAssembly are not currently supported.
  • Start a WuKongIM single-node cluster or multi-node cluster with a healthy /readyz and a reachable WebSocket Gateway. A single-node cluster still follows cluster semantics and defaults to 256 hash slots.
  • Have your trusted backend supply separate uid, token, and websocketUrl values for Alice and Bob. Clients do not call Product HTTP management routes such as /user/token or /route.
  • C# defaults to PC/Desktop 2. The backend token's device_flag must match the client; APP is 0 and Web is 1.

Read Identity & Token first. Production uses HTTPS/WSS with certificate validation. Tokens do not belong in URLs, logs, or source code.

1. Install the NuGet release

dotnet new console -n MyChat --framework net8.0
dotnet add MyChat/MyChat.csproj package WuKongEasySDK --version 1.0.0 --source https://api.nuget.org/v3/index.json

Optional: build from pinned source

git clone https://github.com/WuKongIM/WuKongEasySDK-CSharp.git
git -C WuKongEasySDK-CSharp checkout 02ea7d60cd94feef1996f41bca35ffc3b8e18ea6
dotnet new console -n MyChat --framework net8.0
dotnet add MyChat/MyChat.csproj reference WuKongEasySDK-CSharp/src/WuKongEasySDK/WuKongEasySDK.csproj

The two directories are siblings. Record the exact source revision in your build configuration or maintain the reference through a submodule pinned to that commit.

For a local NuGet installation, build the package from that pinned checkout:

cd WuKongEasySDK-CSharp
dotnet pack src/WuKongEasySDK -c Release -o artifacts
dotnet add ../MyChat/MyChat.csproj package WuKongEasySDK --version 1.0.0 --source ./artifacts

Choose one of the public package, project reference, or local package. Do not combine them. Here, --source ./artifacts is the local feed you just built.

2. Obtain connection material from your backend

After product login, retrieve this minimal response through a protected product route:

{
  "uid": "alice",
  "token": "backend-issued-desktop-token",
  "websocketUrl": "wss://im.example.com/ws"
}

The console example reads these values from WUKONGIM_WS_URL, WUKONGIM_UID, and WUKONGIM_TOKEN. A desktop application can consume the login response directly. These variables belong to the example; they are not the server's WK_ configuration keys.

3. Connect, subscribe, and send

Replace MyChat/Program.cs with the following. Set the three environment variables for the current identity and supply the other user's UID as a command-line argument.

using WuKongEasySDK;

static string Required(string name) =>
    Environment.GetEnvironmentVariable(name)
    ?? throw new InvalidOperationException($"Missing {name}");

if (args.Length != 1)
    throw new ArgumentException("Pass the peer UID as the first argument.");

await using var im = new WKIM(Required("WUKONGIM_WS_URL"), new AuthOptions
{
    Uid = Required("WUKONGIM_UID"),
    Token = Required("WUKONGIM_TOKEN"),
    DeviceFlag = DeviceFlag.Desktop
}, new WKIMOptions
{
    ConnectTimeout = TimeSpan.FromSeconds(10),
    RequestTimeout = TimeSpan.FromSeconds(15)
});

Action<RecvMessage> onMessage = message =>
{
    // Deduplicate by MessageId and pass Payload to application state.
    // Marshal WinForms/WPF updates to the UI thread; do not log full messages.
    Console.WriteLine("Message received.");
};
im.Message += onMessage;
im.Connected += _ => Console.WriteLine("Connected.");
im.Disconnected += _ => Console.WriteLine("Disconnected.");
im.Error += _ => Console.WriteLine("SDK operation failed.");
im.CustomEvent += notification =>
{
    // Route notification.Data using notification.Type.
};

try
{
    await im.ConnectAsync();
    Console.WriteLine("Start the peer, then press Enter to send.");
    Console.ReadLine();
    var result = await im.SendAsync(args[0], ChannelType.Person,
        new { type = 1, content = "Hello from C# 👋" });
    if (!result.IsSuccess)
        Console.WriteLine($"SEND rejected: {(int)result.ReasonCode}");
    else
        Console.WriteLine("Server accepted SEND.");
    Console.WriteLine("Press Enter after checking both directions to exit.");
    Console.ReadLine();
}
finally
{
    im.Message -= onMessage;
    await im.DisconnectAsync();
}

In separate terminals using Alice and Bob's connection material, run dotnet run --project MyChat -- bob and dotnet run --project MyChat -- alice. Async methods return exceptions to their callers and background failures also raise Error; provide application handling for authentication failures, timeouts, and business rejections.

SDK logging is disabled by default. Setting WKIMOptions.DebugLogger enables only fixed operational strings, excluding tokens, payloads, raw frames, and server error bodies.

4. Groups, send results, and received data

Use ChannelType.Group with a backend-managed group ID for group messages. Membership and permissions remain server decisions. SendOptions provides ClientMsgNo, Header, Setting, and Topic. The default header sets RedDot = true; an explicitly supplied header is respected.

ReasonCode.Success is 1. SendResult.IsSuccess means the server accepted SEND, not that Bob received, displayed, or read it. Business rejection codes such as 128–255 remain in the result. JSON-RPC errors throw WKIMRpcException with a numeric Code.

Message IDs use string; numeric wire IDs never pass through floating-point conversion. MessageSeq and NodeId use ulong. Message Timestamp is Unix seconds; custom event Timestamp is Unix milliseconds.

RecvMessage.Payload and EventNotification.Data are independently owned JsonElement values. Receive payloads accept JSON objects or Base64 JSON; undecodable strings remain unchanged. Custom event JSON strings become JSON values, while plain strings remain strings.

5. Reconnect, cancellation, and cleanup

BehaviorC# SDK contract
Instance ownershipnew WKIM / WKIM.Init creates an independent instance; no implicit global singleton
Concurrent connectsConnectAsync callers share the attempt; canceling one cancels only its wait
Stop shared connectionAwait DisconnectAsync before connecting again
Initial failureWebSocket open and authentication share a 10-second budget; failure returns directly
Loss after connectionUp to five retries by default, at 1, 2, 4, 8, and 16 seconds; success resets the budget
Stop automatic retryAuthentication rejection, server disconnect/kick, manual disconnect, or disposal
Final cleanupAwait DisposeAsync from lifecycle code, or use await using

For token rotation or account switching, dispose the old instance and create one with fresh backend-issued credentials. Set AuthOptions.DeviceId explicitly when the device identifier should persist across processes.

Events run serially in the background. Keep handlers short; do not synchronously wait for SDK async operations or wait for disposal inside a callback. A throwing handler does not prevent other listeners or automatic ACK. Already queued callbacks may finish after listener removal or disconnect; DisposeAsync waits for them to drain.

RECVACK means admission to the SDK receive queue, not successful business processing. Defaults are 256 pending requests, 128 queued events, and 1 MiB per complete JSON-RPC envelope. Excess requests throw WKIMBackpressureException; a full event queue closes the connection without ACKing the unaccepted message. Configure these bounds through WKIMOptions.

The SDK does not queue offline messages or automatically resend SEND. A timeout, cancellation, or disconnect may leave the send outcome uncertain. Reconcile business state first; reuse SendOptions.ClientMsgNo when retrying the same logical message. Your application owns offline recovery, conversations, unread counts, push, and business receipts.

6. Run the official example and acceptance

From the pinned checkout:

dotnet build -c Release
dotnet test -c Release
dotnet run --project examples/ConsoleChat -- bob

The console example uses the same environment variables. Type text to send, and use /quit or Ctrl+C to exit. It displays message text as chat UI without printing complete protocol objects.

With a prebuilt server binary, run the automated real-process fixture:

WUKONGIM_BINARY=/absolute/path/to/wukongim python3 scripts/smoke.py

The script starts and cleans up only its own loopback single-node cluster with 256 hash slots and Token authentication. It prepares two test identities and verifies matching SENDACK/RECV for bidirectional Unicode messages, reconnect, heartbeat, and invalid-token rejection.

The original implementation d365a354f5e0f25fbd7f83bb59aa365ba43e899f passed 35 tests, Release builds, and local NuGet packing on macOS arm64 with .NET SDK 8.0.424 / runtime 8.0.30. It also passed the real-process fixture against WuKongIM 132e46209d98fa0425cc0f88e7a97080cdad044d. Loopback WebSocket tests cover custom events and reconnect failures. This receipt excludes public NuGet downloads, production WSS, offline recovery, multi-node capacity, and long-duration stability.

The independent NuGet 1.0.0 release verification covers builds, 35 SDK tests, seven release guard tests, and clean local package installation on Windows, Linux, and macOS. After publication it downloads the exact version from nuget.org, compares every entry except NuGet’s signature with the tested artifact, and restores, compiles, loads, and disposes the client in an isolated project with an empty package cache and only the public feed. This public installation receipt is separate from the real-server messaging receipt above.

C# / JavaScript interoperability

The earlier independent C#/JS interoperability CI tests both public NuGet WuKongEasySDK 1.0.0 restored into an empty package cache and candidate C# source. It pins npm easyjssdk 2.0.4, Node 24 with ws 8.21.3, and server v3.0.0-beta.9 / 734166e0ec30fc0f6f10fef6f6d1889d079ab636. Harness source 1db387c4f794a45bdb6f4e419d68dbe2bfef740f is recorded separately from the NuGet package source.

Five scenario groups cover bidirectional Chinese/emoji and nested custom payloads, exact message IDs above JavaScript's safe integer range and matching SENDACK/RECV, invalid Token rejection, automatic network recovery, real server crash/restart, and manual disconnect with rejected offline SEND followed by explicit reconnect. This server omits clientMsgNo in SENDACK; RECV must preserve the supplied correlation value.

The earlier reproduction record covers Node with ws. The native Node reconnect stall observed there is addressed by the separately identified source repair and acceptance below.

Chromium/WSS and native Node recovery

The earlier extended interoperability CI tests both public NuGet 1.0.0 and candidate C# source with Node 24.3.0 native WebSocket and real Chromium driven by Playwright 1.62.1. It retains server pin 734166e0ec30fc0f6f10fef6f6d1889d079ab636 and pins repaired JS source 5e5dfb727fb0ea08294939962ae799e998b7ca5c. The repair settles handshake failures that emit error without a subsequent close, allowing bounded retries to continue. npm easyjssdk 2.0.4 does not contain this repair.

The browser opens a real HTTPS page and connects over WSS; C# uses its existing ClientWebSocket. A temporary CA and isolated browser NSS trust database preserve normal certificate validation. Both clients must reject untrusted CA and mismatched-host certificates without forwarding decrypted application requests to the server protocol. These controls precede the five bidirectional messaging, invalid Token, network recovery, server restart, and manual disconnect scenarios.

The JS repair is now published in npm easyjssdk 2.0.5, from source b6d0bbe822b9c5b6f95a10d55b593d30184414f6. The public-package interoperability CI installs that exact npm package into an empty cache. All six combinations of released NuGet / candidate C# with ws, native Node, and Chromium WSS passed, including the certificate rejection controls above.

That single-node matrix runs four Linux jobs, producing six reports that retain the npm tarball URL and SHA-512 integrity, actual harness commit, Chromium version, and certificate controls. See reproduction and trust scope. This verifies the temporary CA, loopback TLS proxy, and Chromium; it does not establish every public CA, reverse proxy, Firefox/WebKit, multi-node capacity, or long-duration stability.

Three-node clusters and application address replacement

Complete three-node fault recovery acceptance has not passed. Server migration, recovery log conflicts, and post-rejoin delivery findings are tracked in issue 927. This task covers SDK work, tests, and documentation; earlier unmerged server experiments are not released capability evidence. The passing single-node WS/WSS results above retain their own exact versions and run records.

The application owns address replacement. Each SDK instance retries its fixed endpoint. A trusted backend selects a live ingress and obtains its /route. Await DisposeAsync on the previous instance, then create a replacement with the new URL and existing credentials, register handlers, and connect. An interrupted SEND may have an unknown outcome; do not automatically replay acknowledged or ambiguous messages.

The manual three-node reproduction pins public NuGet WuKongEasySDK 1.0.0, npm easyjssdk 2.0.5, Node 24.3.0, and released server v3.0.0-beta.9 source 734166e0ec30fc0f6f10fef6f6d1889d079ab636. Three loopback processes use 256 hash slots, 10 logical Slots, and three replicas. The fixture checks cross-ingress person/group messages, disconnect and offline-send rejection, application instance replacement, and rejoin with strict ACK/RECV correlation and payload checks. Node readiness and full ISR metadata do not prove physical replica catch-up.

Regular push/PR CI runs four single-node jobs and produces six WS/native Node/Chromium WSS reports. Manual dispatch with include_cluster=true adds two cluster reproduction jobs. Server blockers fail those jobs normally and do not count as passing SDK cluster acceptance. Run locally with python3 scripts/interop.py --transport native --topology three-node, adding --candidate for C# source and supplying the exact server binary as documented by the fixture.

The reproduction records login delays under the default 90-second presence lease and its explicit migration scan budget. Bounded retry of the observed activation error 15 is a reproduction control, not advice to retry arbitrary system errors or SENDs. It does not establish complete three-node recovery, immediate address switching, multi-node WSS, offline synchronization, large-group capacity, or long-duration stability.

Next

See Run the Official Examples and the SDK validation record, or return to WuKongEasySDK to compare platforms. Continue production integration with Messaging and Integration Acceptance.

On this page