SetNet.Streams
1.2.0
dotnet add package SetNet.Streams --version 1.2.0
NuGet\Install-Package SetNet.Streams -Version 1.2.0
<PackageReference Include="SetNet.Streams" Version="1.2.0" />
<PackageVersion Include="SetNet.Streams" Version="1.2.0" />
<PackageReference Include="SetNet.Streams" />
paket add SetNet.Streams --version 1.2.0
#r "nuget: SetNet.Streams, 1.2.0"
#:package SetNet.Streams@1.2.0
#addin nuget:?package=SetNet.Streams&version=1.2.0
#tool nuget:?package=SetNet.Streams&version=1.2.0
<p align="center"> <img src="https://raw.githubusercontent.com/Povstalez/SetNet/master/assets/icon.png" alt="SetNet" width="96"> </p>
SetNet.Streams
Large-payload streaming for SetNet: patches, avatars, replays — offered, chunked, resumable.
Regular messages are for kilobytes; this package is for the megabytes. A transfer starts with an offer (name + size) the receiver can accept or reject, then flows as sequential chunks into a pluggable sink (memory or file), with progress on the sender and resume after a dropped connection — an interrupted upload retried with the same id re-sends only the missing tail. Works in both directions (client → server uploads, server → client pushes). Added by composition — no base class.
Install
dotnet add package SetNet
dotnet add package SetNet.Streams
Usage
Call StreamsRuntime.Enable() once at startup on both ends (before handler discovery).
Server — receive uploads:
StreamsRuntime.Enable();
var streams = server.UseStreams();
streams.Received += (peer, s) =>
{
var bytes = ((MemoryStreamSink)s.Sink).ToArray();
Console.WriteLine($"{peer.CurrentPeerInfo.Id} sent '{s.Name}' ({s.Length} B)");
};
Client — upload with progress and resume:
StreamsRuntime.Enable();
var streams = client.UseStreams();
var progress = new Progress<double>(p => DrawBar(p));
try
{
await streams.SendAsync("replay.dat", File.OpenRead("replay.dat"), progress);
}
catch (StreamsException ex) // connection dropped mid-upload
{
await client.ConnectAsync();
await streams.SendAsync("replay.dat", File.OpenRead("replay.dat"), progress,
streamId: ex.StreamId); // resumes — only the tail is re-sent
}
Large / sensitive offers — decide per offer, stream to disk:
streams.OfferReceived += async offer =>
{
if (offer.Length > 1_000_000_000) { await offer.RejectAsync("Too big."); return; }
await offer.AcceptAsync(new FileStreamSink($"incoming/{offer.StreamId}.bin"));
};
Server → client works the same: await streams.SendAsync(peer, "map.pak", content).
API
| Member | Purpose |
|---|---|
server.UseStreams(StreamsOptions?) → StreamsServer |
hub: SendAsync(peer, ...) + OfferReceived/Received events (per peer) |
client.UseStreams(StreamsOptions?) → StreamsClient |
driver: SendAsync(...) + OfferReceived/Received events |
SendAsync(name, Stream/byte[], IProgress<double>?, Guid? streamId, ct) |
offer + chunked upload; returns the transfer id; same id ⇒ resume |
IncomingStreamOffer.AcceptAsync(IStreamSink?) / RejectAsync(reason) |
per-offer decision (default sink = memory) |
IStreamSink / MemoryStreamSink / FileStreamSink |
where the bytes go |
StreamsOptions |
AutoAccept (default on, ≤ MaxAutoAcceptBytes 64 MB), ChunkSize (64 KB), OfferTimeoutMs, PartialTtlSeconds |
StreamsRuntime.Enable() |
one-time bootstrap so the handlers are discovered |
Notes
- Reserved wire types 65492 / 65493. Don't reuse them.
- Needs a reliable, ordered path. Chunks are validated to be exactly contiguous; run over TCP / WebSockets / UDP-reliable. Over reliable UDP set
ChunkSize≈ 1 KB (datagram limit); over TCP keep it well underConfiguration.MaxMessageSize. - Resume is receiver-driven. The receiver keeps interrupted partials for
PartialTtlSecondskeyed by stream id; the accept reply tells the sender where to continue. Use aFileStreamSinkfor partials that must survive a receiver restart. - Back-pressure. Chunks are awaited one at a time through the normal send path, so
MaxInFlightMessages/SendTimeoutMsapply; a stream saturates the connection while active — pair withSetNet.Multiplexto keep latency-critical traffic on its own dispatch lane. - Trust. An offer's size cap is enforced (
MaxAutoAcceptBytes, overrun checks), but accept-all-from-anyone is still a storage giveaway — gate withSetNet.Authand decide inOfferReceivedfor anything user-generated.
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.2.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.2.0 | 147 | 8/5/2026 |