SetNet.Relay
1.1.0
See the version list below for details.
dotnet add package SetNet.Relay --version 1.1.0
NuGet\Install-Package SetNet.Relay -Version 1.1.0
<PackageReference Include="SetNet.Relay" Version="1.1.0" />
<PackageVersion Include="SetNet.Relay" Version="1.1.0" />
<PackageReference Include="SetNet.Relay" />
paket add SetNet.Relay --version 1.1.0
#r "nuget: SetNet.Relay, 1.1.0"
#:package SetNet.Relay@1.1.0
#addin nuget:?package=SetNet.Relay&version=1.1.0
#tool nuget:?package=SetNet.Relay&version=1.1.0
<p align="center"> <img src="https://raw.githubusercontent.com/Povstalez/SetNet/master/assets/icon.png" alt="SetNet" width="96"> </p>
SetNet.Relay
A TURN-style relay hub for SetNet.
Some peers simply can't connect to each other directly — symmetric NATs, restrictive firewalls, mobile carriers. SetNet.Relay gives them a fallback: both peers connect to a shared server, one allocates a relay session (getting a join code), the other joins by code, and from then on either can push opaque bytes that the server forwards to the rest of the session. The relay never inspects the payload, so you can tunnel anything through it — a custom protocol, host-authoritative game traffic, even another framed stream. Added by composition — no base class.
Install
dotnet add package SetNet
dotnet add package SetNet.Relay
Usage
Call RelayRuntime.Enable() once at startup on both ends (before handler discovery).
Server — just turn the hub on:
RelayRuntime.Enable();
server.UseRelay();
Host client — allocate a session and share the code:
RelayRuntime.Enable();
var relay = client.UseRelay();
relay.PeerJoined += id => Console.WriteLine($"peer {id} joined");
relay.PeerLeft += id => Console.WriteLine($"peer {id} left");
relay.Received += (from, data) => Handle(from, data);
string code = await relay.AllocateAsync(maxPeers: 4); // give this code to the others
Guest client — join by code and exchange bytes:
var relay = client.UseRelay();
relay.Received += (from, data) => Handle(from, data);
await relay.JoinAsync(code);
await relay.SendAsync(payload); // → all other members
await relay.SendToAsync(hostPeerId, payload); // → one member
API
Server: server.UseRelay() — enable the relay hub.
Client: var relay = client.UseRelay() → RelayClient
| Member | Purpose |
|---|---|
Task<string> AllocateAsync(int maxPeers = 0) |
create a session (0 = unlimited), join it, return the code |
Task JoinAsync(string code) |
join an existing session (throws RelayException if missing/full) |
Task LeaveAsync() |
leave the session (tolerant of a dropped connection) |
Task SendAsync(byte[] data, DeliveryMethod = Reliable) |
forward bytes to all other members |
Task SendToAsync(uint peerId, byte[] data, DeliveryMethod = Reliable) |
forward bytes to one member |
event Action<uint, byte[]> Received |
(senderPeerId, opaque bytes) for each relayed payload |
event Action<uint> PeerJoined / PeerLeft |
membership changes |
event Action Closed |
the session ended |
uint OwnId / string? Code |
this client's peer id / current session code |
RelayRuntime.Enable() — one-time bootstrap so the relay handlers are discovered.
Notes
- Reserved wire types 65498 / 65499 / 65500. Don't reuse them.
- Opaque forwarding. The relay copies bytes between members and never deserializes them — pick
DeliveryMethod.Unreliablefor latency-tolerant traffic (over a UDP/Both transport) or the defaultReliable. Keep unreliable payloads under the transport's datagram limit (~1200 B on UDP). - Relay vs Rooms. Rooms broadcast typed messages through your serializer and are built for lobby/game membership. Relay forwards raw opaque bytes with a per-sender id and 1:1 addressing — the right tool for NAT fallback and tunnelling. Use Rooms for gameplay; reach for Relay when peers can't connect directly.
- Node-local sessions. Sessions live on the relay server that created them (like Rooms/Voice); run one relay endpoint, or shard clients so both peers of a session land on the same node.
- Secure it. The relay carries whatever bytes it's given to anyone with the code — gate access with
SetNet.Authand run over TLS if the tunnelled traffic is sensitive.
Documentation & source
- 🐙 https://github.com/Povstalez/SetNet — full module catalog in docs/MODULES.md
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- SetNet (>= 1.1.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.